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>