File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / freevrrpd / vrrp_netgraph.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 12:01:54 2017 UTC (7 years ago) by misho
Branches: freevrrpd, MAIN
CVS tags: v1_1, HEAD
freevrrpd 1.1

    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>