Annotation of embedaddon/freevrrpd/vrrp_netgraph.c, revision 1.1.1.1
1.1 misho 1: #include <netgraph.h>
2: #include <netgraph/ng_message.h>
3: #include <netgraph/ng_ether.h>
4: #include <netgraph/ng_eiface.h>
5: #include <syslog.h>
6: #include <stdarg.h>
7: #include <stdio.h>
8: #include <stdlib.h>
9: #include <string.h>
10: #include <unistd.h>
11: #include <errno.h>
12: #include "vrrp_netgraph.h"
13: #include "vrrp_proto.h"
14: #include "vrrp_functions.h"
15:
16: struct ng_mesg *vrrp_netgraph_get_node_list(int);
17:
18: int vrrp_netgraph_open(int *ng_control_socket, int *ng_data_socket) {
19: if (NgMkSockNode(NULL, ng_control_socket, ng_data_socket) < 0) {
20: syslog(LOG_ERR, "cannot create a netgraph socket: %s", strerror(errno));
21: return -1;
22: }
23:
24: return 0;
25: }
26:
27: void vrrp_netgraph_close(int ng_control_socket, int ng_data_socket) {
28: close(ng_control_socket);
29: close(ng_data_socket);
30:
31: return;
32: }
33:
34: int vrrp_netgraph_bridge_create(char *ifname) {
35: struct ngm_mkpeer mkp;
36: struct ngm_name name;
37: struct ngm_connect connect;
38: char path[256];
39: int ng_control_socket, ng_data_socket;
40:
41: if (vrrp_netgraph_open(&ng_control_socket, &ng_data_socket) < 0)
42: return -1;
43:
44: snprintf(mkp.type, sizeof(mkp.type), "bridge");
45: snprintf(mkp.ourhook, sizeof(mkp.ourhook), "lower");
46: snprintf(mkp.peerhook, sizeof(mkp.peerhook), "link0");
47: snprintf(path, sizeof(path), "%s:", ifname);
48:
49: if (NgSendMsg(ng_control_socket, path, NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp, sizeof(mkp)) < 0) {
50: vrrp_netgraph_close(ng_control_socket, ng_data_socket);
51: return -1;
52: }
53:
54: snprintf(name.name, sizeof(name.name), "%s_%sbridge", VRRP_NETGRAPH_BASENAME, ifname);
55: snprintf(path, sizeof(path), "%s:lower", ifname);
56: if (NgSendMsg(ng_control_socket, path, NGM_GENERIC_COOKIE, NGM_NAME, &name, sizeof(name)) < 0) {
57: vrrp_netgraph_close(ng_control_socket, ng_data_socket);
58: return -1;
59: }
60:
61: snprintf(connect.path, sizeof(connect.path), "%s_%sbridge:", VRRP_NETGRAPH_BASENAME, ifname);
62: snprintf(connect.ourhook, sizeof(connect.ourhook), "upper");
63: snprintf(connect.peerhook, sizeof(connect.peerhook), "link1");
64: snprintf(path, sizeof(path), "%s:", ifname);
65: if (NgSendMsg(ng_control_socket, path, NGM_GENERIC_COOKIE, NGM_CONNECT, &connect, sizeof(connect)) < 0) {
66: vrrp_netgraph_close(ng_control_socket, ng_data_socket);
67: return -1;
68: }
69:
70: vrrp_netgraph_close(ng_control_socket, ng_data_socket);
71:
72: return 0;
73: }
74:
75: int vrrp_netgraph_get_ethernet_address(int ng_control_socket, char *path, struct ether_addr *eaddr) {
76: struct ng_mesg *ngmsg;
77:
78: if (NgSendMsg(ng_control_socket, path, NGM_EIFACE_COOKIE, NGM_EIFACE_GET_IFADDRS, NULL, 0) < 0)
79: return -1;
80:
81: if (NgAllocRecvMsg(ng_control_socket, &ngmsg, NULL) < 0) {
82: syslog(LOG_ERR, "cannot get netgraph answer: %s\n", strerror(errno));
83: return -1;
84: }
85:
86: /* XXX SANITY CHECK HERE */
87: bcopy(ngmsg->data, eaddr, sizeof(*eaddr));
88:
89: free(ngmsg);
90: return 0;
91: }
92:
93: int vrrp_netgraph_set_ethernet_address(int ng_control_socket, char *path, struct ether_addr *eaddr) {
94: if (NgSendMsg(ng_control_socket, path, NGM_EIFACE_COOKIE, NGM_EIFACE_SET, eaddr, sizeof(*eaddr)) < 0)
95: return -1;
96:
97: return 0;
98: }
99:
100: int vrrp_netgraph_create_eiface(char *ng_name, char *ether_name, struct ether_addr *ng_eaddr) {
101: struct ngm_mkpeer mkp;
102: struct ng_mesg *ngmsg;
103: char path[256];
104: char name[64];
105: struct nodeinfo *ninfo;
106: struct namelist *nlist;
107: char found = 0;
108: int ng_control_socket, ng_data_socket;
109:
110: if (vrrp_netgraph_open(&ng_control_socket, &ng_data_socket))
111: return -1;
112:
113: snprintf(path, sizeof(path), ".");
114: snprintf(mkp.type, sizeof(mkp.type), "eiface");
115: snprintf(mkp.ourhook, sizeof(mkp.ourhook), "ether");
116: snprintf(mkp.peerhook, sizeof(mkp.peerhook), "ether");
117: if (NgSendMsg(ng_control_socket, path, NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp, sizeof(mkp)) < 0)
118: return -1;
119:
120: vrrp_netgraph_close(ng_control_socket, ng_data_socket);
121:
122: if (vrrp_netgraph_open(&ng_control_socket, &ng_data_socket))
123: return -1;
124:
125: /* Get node list for assigning a name to the newly created eiface */
126: /* libnetgraph lacks of returning ID/name when creating nodes */
127: /* it's a problem... */
128: ngmsg = vrrp_netgraph_get_node_list(ng_control_socket);
129: if (! ngmsg)
130: return -1;
131:
132: nlist = (struct namelist *)ngmsg->data;
133: ninfo = nlist->nodeinfo;
134: while ((nlist->numnames > 0) && (! found)) {
135: if (! strcmp(ninfo->type, "eiface")) {
136: if (! strcmp(ninfo->name, ""))
137: snprintf(ninfo->name, sizeof(ninfo->name), "ngeth0");
138: if (! ninfo->hooks) {
139: snprintf(path, sizeof(path), "[%X]:", ninfo->id);
140: snprintf(ether_name, IFNAMSIZ, "%s", ninfo->name);
141: if (vrrp_netgraph_set_ethernet_address(ng_control_socket, path, ng_eaddr) < 0) {
142: syslog(LOG_ERR, "cannot set ethernet address to %s: %s\n", ninfo->name, strerror(errno));
143: free(ngmsg);
144: return -1;
145: }
146: snprintf(name, sizeof(name), "%s", ng_name);
147: if (NgNameNode(ng_control_socket, path, name) < 0) {
148: free(ngmsg);
149: return -1;
150: }
151: found = 1;
152: }
153: }
154: ninfo++;
155: nlist->numnames--;
156: }
157:
158: free(ngmsg);
159:
160: vrrp_netgraph_close(ng_control_socket, ng_data_socket);
161:
162: return 0;
163: }
164:
165: int vrrp_netgraph_connect_eiface_to_bridge(int ng_control_socket, char *eiface_name, char *ifname, int *link_number) {
166: struct ngm_connect connect;
167: char path[256];
168:
169: NgSetDebug(10);
170:
171: snprintf(path, sizeof(path), "%s:", eiface_name);
172: snprintf(connect.path, sizeof(connect.path), "%s_%sbridge:", VRRP_NETGRAPH_BASENAME, ifname);
173: snprintf(connect.ourhook, sizeof(connect.ourhook), "ether");
174: snprintf(connect.peerhook, sizeof(connect.peerhook), "link%d", *link_number);
175:
176: if (NgSendMsg(ng_control_socket, path, NGM_GENERIC_COOKIE, NGM_CONNECT, &connect, sizeof(connect)) < 0) {
177: syslog(LOG_ERR, "cannot connect path %s to bridge %s with link%d: %s\n", path, connect.path, *link_number, strerror(errno));
178: return -1;
179: }
180:
181: (*link_number)++;
182:
183: return 0;
184: }
185:
186: struct ng_mesg *vrrp_netgraph_get_node_list(int ng_control_socket) {
187: struct ng_mesg *ngmsg;
188:
189: if (NgSendMsg(ng_control_socket, ".", NGM_GENERIC_COOKIE, NGM_LISTNODES, NULL, 0) < 0) {
190: syslog(LOG_ERR, "cannot send netgraph message: %s\n", strerror(errno));
191: return NULL;
192: }
193:
194: if (NgAllocRecvMsg(ng_control_socket, &ngmsg, NULL) < 0) {
195: syslog(LOG_ERR, "cannot get netgraph answer: %s\n", strerror(errno));
196: return NULL;
197: }
198:
199: return ngmsg;
200: }
201:
202: int vrrp_netgraph_create_virtualiface(struct vrrp_vr *vr) {
203: char eiface_name[256];
204: int ng_control_socket, ng_data_socket;
205:
206: snprintf(eiface_name, sizeof(eiface_name), "%s_vrid%d", VRRP_NETGRAPH_BASENAME, vr->vr_id);
207: if (vrrp_netgraph_create_eiface(eiface_name, vr->viface_name, &vr->ethaddr) < 0) {
208: syslog(LOG_ERR, "cannot create an eiface/ether netgraph interface: %s\n", strerror(errno));
209: syslog(LOG_ERR, "ng_ether.ko is probably not loaded, use kldload ng_ether.ko before running freevrrpd\n");
210: fprintf(stderr, "Please load ng_ether manually with kldload ng_ether.ko or add ng_ether_load=\"YES\" into /boot/loader.conf\n");
211: return -1;
212: }
213: if (vrrp_netgraph_open(&ng_control_socket, &ng_data_socket) < 0)
214: return -1;
215: if (vrrp_netgraph_connect_eiface_to_bridge(ng_control_socket, eiface_name, vr->vr_if->if_name, &vr->bridge_link_number) < 0)
216: return -1;
217:
218: vrrp_netgraph_close(ng_control_socket, ng_data_socket);
219:
220: return 0;
221: }
222:
223: int vrrp_netgraph_shutdown_allnodes(void) {
224: struct nodeinfo *ninfo;
225: struct namelist *nlist;
226: struct ng_mesg *ngmsg;
227: char path[256];
228: int ng_control_socket, ng_data_socket;
229:
230: if (vrrp_netgraph_open(&ng_control_socket, &ng_data_socket) < 0)
231: return -1;
232:
233: ngmsg = vrrp_netgraph_get_node_list(ng_control_socket);
234: if (! ngmsg)
235: return -1;
236:
237: nlist = (struct namelist *)ngmsg->data;
238: ninfo = nlist->nodeinfo;
239: while (nlist->numnames > 0) {
240: if (! strncmp(ninfo->name, VRRP_NETGRAPH_BASENAME, strlen(VRRP_NETGRAPH_BASENAME))) {
241: snprintf(path, sizeof(path), "%s:", ninfo->name);
242: vrrp_netgraph_shutdown(ng_control_socket, path);
243: }
244: ninfo++;
245: nlist->numnames--;
246: }
247:
248: free(ngmsg);
249: vrrp_netgraph_close(ng_control_socket, ng_data_socket);
250:
251: return 0;
252: }
253:
254: int vrrp_netgraph_shutdown(int ng_control_socket, char *path) {
255: if (NgSendMsg(ng_control_socket, path, NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0) < 0) {
256: syslog(LOG_ERR, "cannot shutdown netgraph path %s: %s\n", path, strerror(errno));
257: return -1;
258: }
259:
260: return 0;
261: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>