Annotation of embedaddon/freevrrpd/vrrp_netgraph.c, revision 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>