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>