Annotation of embedaddon/mpd/src/ngfunc.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * ngfunc.c
                      4:  *
                      5:  * Written by Archie Cobbs <archie@freebsd.org>
                      6:  * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
                      7:  * See ``COPYRIGHT.whistle''
                      8:  *
                      9:  * TCP MSSFIX contributed by Sergey Korolew <dsATbittu.org.ru>
                     10:  *
                     11:  * Routines for doing netgraph stuff
                     12:  *
                     13:  */
                     14: 
                     15: #include "defs.h"
                     16: #include "ppp.h"
                     17: #include "bund.h"
                     18: #include "ngfunc.h"
                     19: #include "input.h"
                     20: #include "ccp.h"
                     21: #include "netgraph.h"
                     22: #include "command.h"
                     23: #include "util.h"
                     24: 
                     25: #ifdef USE_NG_BPF
                     26: #include <net/bpf.h>
                     27: #endif
                     28: #include <arpa/inet.h>
                     29: 
                     30: #include <netgraph/ng_message.h>
                     31: 
                     32: #include <netgraph/ng_socket.h>
                     33: #include <netgraph/ng_ksocket.h>
                     34: #include <netgraph/ng_iface.h>
                     35: #ifdef USE_NG_VJC
                     36: #include <netgraph/ng_vjc.h>
                     37: #endif
                     38: #ifdef USE_NG_BPF
                     39: #include <netgraph/ng_bpf.h>
                     40: #endif
                     41: #include <netgraph/ng_tee.h>
                     42: #ifdef USE_NG_TCPMSS
                     43: #include <netgraph/ng_tcpmss.h>
                     44: #endif
                     45: #ifdef USE_NG_NETFLOW
                     46: #include <netgraph/netflow/ng_netflow.h>
                     47: #if NGM_NETFLOW_COOKIE >= 1309868867
                     48: #include <netgraph/netflow/netflow.h>
                     49: #include <netgraph/netflow/netflow_v9.h>
                     50: #endif
                     51: #endif
                     52: #ifdef USE_NG_PRED1
                     53: #include <netgraph/ng_pred1.h>
                     54: #endif
                     55: 
                     56: #include <netinet/ip_icmp.h>
                     57: #include <netinet/tcp.h>
                     58: 
                     59: /*
                     60:  * DEFINITIONS
                     61:  */
                     62: 
                     63:   #define TEMPHOOK             "temphook"
                     64:   #define MAX_IFACE_CREATE     128
                     65: 
                     66:   /* Set menu options */
                     67:   enum {
                     68:     SET_PEER,
                     69:     SET_SELF,
                     70:     SET_TIMEOUTS,
                     71: #if NGM_NETFLOW_COOKIE >= 1309868867
                     72:     SET_TEMPLATE,
                     73:     SET_MTU,
                     74:     SET_VERSION,
                     75: #endif
                     76:     SET_NODE,
                     77:     SET_HOOK
                     78:   };
                     79: 
                     80: /*
                     81:  * INTERNAL FUNCTIONS
                     82:  */
                     83: 
                     84: #ifdef USE_NG_NETFLOW
                     85:   static int   NetflowSetCommand(Context ctx, int ac, char *av[], void *arg);
                     86: #endif
                     87: 
                     88: /*
                     89:  * GLOBAL VARIABLES
                     90:  */
                     91: 
                     92: #ifdef USE_NG_NETFLOW
                     93:   const struct cmdtab NetflowSetCmds[] = {
                     94:     { "peer {ip} {port}",      "Set export destination" ,
                     95:         NetflowSetCommand, NULL, 2, (void *) SET_PEER },
                     96:     { "self {ip} [{port}]",    "Set export source" ,
                     97:         NetflowSetCommand, NULL, 2, (void *) SET_SELF },
                     98:     { "timeouts {inactive} {active}", "Set NetFlow timeouts" ,
                     99:         NetflowSetCommand, NULL, 2, (void *) SET_TIMEOUTS },
                    100: #if NGM_NETFLOW_COOKIE >= 1309868867
                    101:     { "template {time} {packets}", "Set NetFlow v9 template" ,
                    102:         NetflowSetCommand, NULL, 2, (void *) SET_TEMPLATE },
                    103:     { "mtu {mtu}", "Set NetFlow v9 MTU" ,
                    104:         NetflowSetCommand, NULL, 2, (void *) SET_MTU },
                    105:     { "version {version}", "Set version to export" ,
                    106:         NetflowSetCommand, NULL, 2, (void *) SET_VERSION },
                    107: #endif
                    108:     { "node {name}", "Set node name to use" ,
                    109:         NetflowSetCommand, NULL, 2, (void *) SET_NODE },
                    110:     { "hook {number}", "Set initial hook number" ,
                    111:         NetflowSetCommand, NULL, 2, (void *) SET_HOOK },
                    112:     { NULL },
                    113:   };
                    114: #endif
                    115: 
                    116: /*
                    117:  * INTERNAL VARIABLES
                    118:  */
                    119: 
                    120: #ifdef USE_NG_TCPMSS
                    121:   u_char gTcpMSSNode = FALSE;
                    122: #endif
                    123: #ifdef USE_NG_NETFLOW
                    124:   u_char gNetflowNode = FALSE;
                    125:   u_char gNetflowNodeShutdown = TRUE;
                    126:   char gNetflowNodeName[64] = "mpd-nf";
                    127:   ng_ID_t gNetflowNodeID = 0;
                    128:   u_int gNetflowIface = 0;
                    129:   struct sockaddr_storage gNetflowExport;
                    130:   struct sockaddr_storage gNetflowSource;
                    131:   uint32_t gNetflowInactive = 0;
                    132:   uint32_t gNetflowActive = 0;
                    133: #if NGM_NETFLOW_COOKIE >= 1309868867
                    134:   uint16_t gNetflowTime = 0;
                    135:   uint16_t gNetflowPackets = 0;
                    136:   uint16_t gNetflowMTU = 0;
                    137:   u_int gNetflowVer = 5;
                    138: #endif
                    139: #endif
                    140:   
                    141:   static int   gNgStatSock=0;
                    142: 
                    143: 
                    144: #ifdef USE_NG_NETFLOW
                    145: int
                    146: NgFuncInitGlobalNetflow(void)
                    147: {
                    148:     char               path[NG_PATHSIZ];
                    149:     struct ngm_mkpeer  mp;
                    150:     struct ngm_rmhook  rm;
                    151:     struct ngm_name    nm;
                    152:     int                        csock;
                    153: 
                    154:     /* Create a netgraph socket node */
                    155:     if (NgMkSockNode(NULL, &csock, NULL) < 0) {
                    156:        Perror("NETFLOW: Can't create %s node", NG_SOCKET_NODE_TYPE);
                    157:         return (-1);
                    158:     }
                    159: 
                    160:     /* If node exist just get it's ID. */
                    161:     if (gNetflowNode) {
                    162:        snprintf(path, sizeof(path), "%s:", gNetflowNodeName);
                    163:        gNetflowNodeID = NgGetNodeID(csock, path);
                    164:        close(csock);
                    165:        return (0);
                    166:     }
                    167: 
                    168:     snprintf(gNetflowNodeName, sizeof(gNetflowNodeName), "mpd%d-nf", gPid);
                    169: 
                    170:     /* Create a global netflow node. */
                    171:     strcpy(mp.type, NG_NETFLOW_NODE_TYPE);
                    172:     strcpy(mp.ourhook, TEMPHOOK);
                    173:     strcpy(mp.peerhook, NG_NETFLOW_HOOK_DATA "0");
                    174:     if (NgSendMsg(csock, ".:",
                    175:       NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                    176:        Perror("NETFLOW: Can't create %s node at \"%s\"->\"%s\"", 
                    177:            mp.type, ".:", mp.ourhook);
                    178:        goto fail;
                    179:     }
                    180:     
                    181:     /* Get new node ID. */
                    182:     gNetflowNodeID = NgGetNodeID(csock, TEMPHOOK);
                    183: 
                    184:     /* Set the new node's name. */
                    185:     strcpy(nm.name, gNetflowNodeName);
                    186:     if (NgSendMsg(csock, TEMPHOOK,
                    187:       NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                    188:        Perror("NETFLOW: Can't name %s node", NG_NETFLOW_NODE_TYPE);
                    189:        goto fail;
                    190:     }
                    191: 
                    192:     /* Connect ng_ksocket(4) node for export. */
                    193:     strcpy(mp.type, NG_KSOCKET_NODE_TYPE);
                    194: #if NGM_NETFLOW_COOKIE >= 1309868867
                    195:     if (gNetflowVer == 5) {
                    196: #endif
                    197:        strcpy(mp.ourhook, NG_NETFLOW_HOOK_EXPORT);
                    198: #if NGM_NETFLOW_COOKIE >= 1309868867
                    199:     } else {
                    200:        strcpy(mp.ourhook, NG_NETFLOW_HOOK_EXPORT9);
                    201:     }
                    202: #endif
                    203:     if (gNetflowExport.ss_family==AF_INET6) {
                    204:        snprintf(mp.peerhook, sizeof(mp.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
                    205:     } else {
                    206:         snprintf(mp.peerhook, sizeof(mp.peerhook), "inet/dgram/udp");
                    207:     }
                    208:     snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
                    209:     if (NgSendMsg(csock, path,
                    210:       NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                    211:        Perror("NETFLOW: Can't create %s node at \"%s\"->\"%s\"",
                    212:            mp.type, path, mp.ourhook);
                    213:        goto fail;
                    214:     }
                    215: 
                    216:     /* Configure timeouts for ng_netflow(4). */
                    217:     if (gNetflowInactive != 0 && gNetflowActive != 0) {
                    218:        struct ng_netflow_settimeouts nf_settime;
                    219: 
                    220:        nf_settime.inactive_timeout = gNetflowInactive;
                    221:        nf_settime.active_timeout = gNetflowActive;
                    222: 
                    223:        if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
                    224:          NGM_NETFLOW_SETTIMEOUTS, &nf_settime, sizeof(nf_settime)) < 0) {
                    225:            Perror("NETFLOW: Can't set timeouts on netflow %s node",
                    226:                NG_NETFLOW_NODE_TYPE);
                    227:            goto fail2;
                    228:        }
                    229:     }
                    230: 
                    231: #if NGM_NETFLOW_COOKIE >= 1309868867
                    232:     if (gNetflowTime != 0 && gNetflowPackets != 0) {
                    233:        struct ng_netflow_settemplate nf_settempl;
                    234: 
                    235:        nf_settempl.time = gNetflowTime;
                    236:        nf_settempl.packets = gNetflowPackets;
                    237:        if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
                    238:          NGM_NETFLOW_SETTEMPLATE, &nf_settempl, sizeof(nf_settempl)) < 0) {
                    239:            Perror("NETFLOW: Can't set NetFlow v9 template on netflow %s node",
                    240:                NG_NETFLOW_NODE_TYPE);
                    241:            goto fail2;
                    242:        }
                    243:     }
                    244: 
                    245:     if (gNetflowMTU != 0) {
                    246:        struct ng_netflow_setmtu nf_setmtu;
                    247: 
                    248:        nf_setmtu.mtu = gNetflowMTU;
                    249:        if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
                    250:          NGM_NETFLOW_SETMTU, &nf_setmtu, sizeof(nf_setmtu)) < 0) {
                    251:            Perror("NETFLOW: Can't set NetFlow v9 MTU on netflow %s node",
                    252:                NG_NETFLOW_NODE_TYPE);
                    253:          goto fail2;
                    254:        }
                    255:     }
                    256: #endif
                    257: 
                    258:     /* Configure export destination and source on ng_ksocket(4). */
                    259: #if NGM_NETFLOW_COOKIE >= 1309868867
                    260:     if (gNetflowVer == 5) {
                    261: #endif
                    262:        strlcat(path, NG_NETFLOW_HOOK_EXPORT, sizeof(path));
                    263: #if NGM_NETFLOW_COOKIE >= 1309868867
                    264:     } else {
                    265:        strlcat(path, NG_NETFLOW_HOOK_EXPORT9, sizeof(path));
                    266:     }
                    267: #endif
                    268:     if (gNetflowSource.ss_len != 0) {
                    269:        if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
                    270:          NGM_KSOCKET_BIND, &gNetflowSource, sizeof(gNetflowSource)) < 0) {
                    271:            Perror("NETFLOW: Can't bind export %s node", NG_KSOCKET_NODE_TYPE);
                    272:            goto fail2;
                    273:        }
                    274:     }
                    275:     if (gNetflowExport.ss_len != 0) {
                    276:        if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
                    277:          NGM_KSOCKET_CONNECT, &gNetflowExport, sizeof(gNetflowExport)) < 0) {
                    278:            Perror("NETFLOW: Can't connect export %s node", NG_KSOCKET_NODE_TYPE);
                    279:            goto fail2;
                    280:        }
                    281:     }
                    282: 
                    283:     /* Set the new node's name. */
                    284:     snprintf(nm.name, sizeof(nm.name), "mpd%d-nfso", gPid);
                    285:     if (NgSendMsg(csock, path,
                    286:       NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                    287:        Perror("NETFLOW: Can't name %s node", NG_KSOCKET_NODE_TYPE);
                    288:        goto fail2;
                    289:     }
                    290: 
                    291:     /* Disconnect temporary hook. */
                    292:     memset(&rm, 0, sizeof(rm));
                    293:     strncpy(rm.ourhook, TEMPHOOK, sizeof(rm.ourhook));
                    294:     if (NgSendMsg(csock, ".:",
                    295:       NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
                    296:        Perror("can't remove hook %s", TEMPHOOK);
                    297:        goto fail2;
                    298:     }
                    299:     gNetflowNode = TRUE;
                    300:     close(csock);
                    301: 
                    302:     return (0);
                    303: fail2:
                    304:     snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
                    305:     NgFuncShutdownNode(csock, "netflow", path);
                    306: fail:
                    307:     gNetflowNodeID = 0;
                    308:     close(csock);
                    309:     return (-1);
                    310: }
                    311: #endif
                    312: 
                    313: /*
                    314:  * NgFuncCreateIface()
                    315:  *
                    316:  * Create a new netgraph interface.
                    317:  */
                    318: 
                    319: int
                    320: NgFuncCreateIface(Bund b, char *buf, int max)
                    321: {
                    322:     union {
                    323:         u_char         buf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
                    324:         struct ng_mesg reply;
                    325:     }                  u;
                    326:     struct nodeinfo    *const ni = (struct nodeinfo *)(void *)u.reply.data;
                    327:     struct ngm_rmhook  rm;
                    328:     struct ngm_mkpeer  mp;
                    329:     int                        rtn = 0;
                    330: 
                    331:     /* Create iface node (as a temporary peer of the socket node) */
                    332:     strcpy(mp.type, NG_IFACE_NODE_TYPE);
                    333:     strcpy(mp.ourhook, TEMPHOOK);
                    334:     strcpy(mp.peerhook, NG_IFACE_HOOK_INET);
                    335:     if (NgSendMsg(gLinksCsock, ".:",
                    336:       NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                    337:        Log(LG_ERR, ("[%s] can't create %s node at \"%s\"->\"%s\": %s %d",
                    338:            b->name, NG_IFACE_NODE_TYPE, ".:", mp.ourhook, strerror(errno), gLinksCsock));
                    339:        return(-1);
                    340:     }
                    341: 
                    342:     /* Get the new node's name */
                    343:     if (NgSendMsg(gLinksCsock, TEMPHOOK,
                    344:       NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0) {
                    345:        Perror("[%s] %s", b->name, "NGM_NODEINFO");
                    346:        rtn = -1;
                    347:        goto done;
                    348:     }
                    349:     if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0) {
                    350:        Perror("[%s] reply from %s", b->name, NG_IFACE_NODE_TYPE);
                    351:        rtn = -1;
                    352:        goto done;
                    353:     }
                    354:     strlcpy(buf, ni->name, max);
                    355: 
                    356: done:
                    357:     /* Disconnect temporary hook */
                    358:     strcpy(rm.ourhook, TEMPHOOK);
                    359:     if (NgSendMsg(gLinksCsock, ".:",
                    360:       NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
                    361:        Perror("[%s] can't remove hook %s", b->name, TEMPHOOK);
                    362:        rtn = -1;
                    363:     }
                    364: 
                    365:     /* Done */
                    366:     return(rtn);
                    367: }
                    368: 
                    369: /*
                    370:  * NgFuncShutdownGlobal()
                    371:  *
                    372:  * Shutdown nodes, that are shared between bundles.
                    373:  */
                    374: 
                    375: void
                    376: NgFuncShutdownGlobal(void)
                    377: {
                    378: #ifdef USE_NG_NETFLOW
                    379:     char       path[NG_PATHSIZ];
                    380:     int                csock;
                    381: 
                    382:     if (gNetflowNode == FALSE || gNetflowNodeShutdown==FALSE)
                    383:        return;
                    384: 
                    385:     /* Create a netgraph socket node */
                    386:     if (NgMkSockNode(NULL, &csock, NULL) < 0) {
                    387:        Perror("NgFuncShutdownGlobal: can't create %s node", NG_SOCKET_NODE_TYPE);
                    388:        return;
                    389:     }
                    390: 
                    391:     snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
                    392:     NgFuncShutdownNode(csock, "netflow", path);
                    393:     
                    394:     close(csock);
                    395: #endif
                    396: }
                    397: 
                    398: /*
                    399:  * NgFuncShutdownNode()
                    400:  */
                    401: 
                    402: int
                    403: NgFuncShutdownNode(int csock, const char *label, const char *path)
                    404: {
                    405:     int rtn, retry = 10, delay = 1000;
                    406: 
                    407: retry:
                    408:     if ((rtn = NgSendMsg(csock, path,
                    409:       NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0)) < 0) {
                    410:        if (errno == ENOBUFS && retry > 0) {
                    411:            Log(LG_ERR, ("[%s] shutdown \"%s\": %s, retrying...",
                    412:              label, path, strerror(errno)));
                    413:            usleep(delay);
                    414:            retry--;
                    415:            delay *= 2;
                    416:            goto retry;
                    417:        }
                    418:        if (errno != ENOENT) {
                    419:            Perror("[%s] can't shutdown \"%s\"", label, path);
                    420:        }
                    421:     }
                    422:     return(rtn);
                    423: }
                    424: 
                    425: /*
                    426:  * NgFuncSetConfig()
                    427:  */
                    428: 
                    429: void
                    430: NgFuncSetConfig(Bund b)
                    431: {
                    432:     char       path[NG_PATHSIZ];
                    433:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    434:     if (NgSendMsg(gLinksCsock, path, NGM_PPP_COOKIE,
                    435:            NGM_PPP_SET_CONFIG, &b->pppConfig, sizeof(b->pppConfig)) < 0) {
                    436:        Perror("[%s] can't config %s", b->name, path);
                    437:        DoExit(EX_ERRDEAD);
                    438:     }
                    439: }
                    440: 
                    441: /*
                    442:  * NgFuncSendQuery()
                    443:  */
                    444: 
                    445: int
                    446: NgFuncSendQuery(const char *path, int cookie, int cmd, const void *args,
                    447:        size_t arglen, struct ng_mesg *rbuf, size_t replen, char *raddr)
                    448: {
                    449: 
                    450:     if (!gNgStatSock) {
                    451:        char            name[NG_NODESIZ];
                    452:        
                    453:        /* Create a netgraph socket node */
                    454:        snprintf(name, sizeof(name), "mpd%d-stats", gPid);
                    455:        if (NgMkSockNode(name, &gNgStatSock, NULL) < 0) {
                    456:            Perror("NgFuncSendQuery: can't create %s node", NG_SOCKET_NODE_TYPE);
                    457:            return(-1);
                    458:        }
                    459:        (void) fcntl(gNgStatSock, F_SETFD, 1);
                    460:     }
                    461: 
                    462:     /* Send message */
                    463:     if (NgSendMsg(gNgStatSock, path, cookie, cmd, args, arglen) < 0)
                    464:        return (-1);
                    465: 
                    466:     /* Read message */
                    467:     if (NgRecvMsg(gNgStatSock, rbuf, replen, raddr) < 0) {
                    468:        Perror("NgFuncSendQuery: can't read unexpected message");
                    469:        return (-1);
                    470:     }
                    471: 
                    472:     return (0);
                    473: }
                    474: 
                    475: /*
                    476:  * NgFuncConnect()
                    477:  */
                    478: 
                    479: int
                    480: NgFuncConnect(int csock, char *label, const char *path, const char *hook,
                    481:        const char *path2, const char *hook2)
                    482: {
                    483:     struct ngm_connect cn;
                    484: 
                    485:     strlcpy(cn.path, path2, sizeof(cn.path));
                    486:     strlcpy(cn.ourhook, hook, sizeof(cn.ourhook));
                    487:     strlcpy(cn.peerhook, hook2, sizeof(cn.peerhook));
                    488:     if (NgSendMsg(csock, path,
                    489:       NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    490:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    491:            label, path, hook, path2, hook2);
                    492:        return(-1);
                    493:     }
                    494:     return(0);
                    495: }
                    496: 
                    497: /*
                    498:  * NgFuncDisconnect()
                    499:  */
                    500: 
                    501: int
                    502: NgFuncDisconnect(int csock, char *label, const char *path, const char *hook)
                    503: {
                    504:     struct ngm_rmhook  rm;
                    505:     int                retry = 10, delay = 1000;
                    506: 
                    507:     /* Disconnect hook */
                    508:     memset(&rm, 0, sizeof(rm));
                    509:     strlcpy(rm.ourhook, hook, sizeof(rm.ourhook));
                    510: retry:
                    511:     if (NgSendMsg(csock, path,
                    512:       NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
                    513:        if (errno == ENOBUFS && retry > 0) {
                    514:            Log(LG_ERR, ("[%s] remove hook %s from node \"%s\": %s, retrying...",
                    515:              label, hook, path, strerror(errno)));
                    516:            usleep(delay);
                    517:            retry--;
                    518:            delay *= 2;
                    519:            goto retry;
                    520:        }
                    521:        Perror("[%s] can't remove hook %s from node \"%s\"", label, hook, path);
                    522:        return(-1);
                    523:     }
                    524:     return(0);
                    525: }
                    526: 
                    527: /*
                    528:  * NgFuncWritePppFrame()
                    529:  *
                    530:  * Consumes the mbuf.
                    531:  */
                    532: 
                    533: int
                    534: NgFuncWritePppFrame(Bund b, int linkNum, int proto, Mbuf bp)
                    535: {
                    536:     u_int16_t  temp;
                    537: 
                    538:     /* Prepend ppp node bypass header */
                    539:     temp = htons(linkNum);
                    540:     bp = mbcopyback(bp, -4, &temp, 2);
                    541:     temp = htons(proto);
                    542:     bp = mbcopyback(bp, 2, &temp, 2);
                    543: 
                    544:     /* Debugging */
                    545:     LogDumpBp(LG_FRAME, bp,
                    546:        "[%s] xmit bypass frame link=%d proto=0x%04x",
                    547:        b->name, (int16_t)linkNum, proto);
                    548: 
                    549:     if ((linkNum == NG_PPP_BUNDLE_LINKNUM && b->n_up == 0) ||
                    550:        (linkNum != NG_PPP_BUNDLE_LINKNUM &&
                    551:            (b->links[linkNum] == NULL ||
                    552:            b->links[linkNum]->state != PHYS_STATE_UP))) {
                    553:        Log(LG_FRAME, ("[%s] Bundle: No links ready to send packet", b->name));
                    554:        mbfree(bp);
                    555:        return (-1);
                    556:     }
                    557: 
                    558:     /* Write frame */
                    559:     return NgFuncWriteFrame(gLinksDsock, b->hook, b->name, bp);
                    560: }
                    561: 
                    562: /*
                    563:  * NgFuncWritePppFrameLink()
                    564:  *
                    565:  * Consumes the mbuf.
                    566:  */
                    567: 
                    568: int
                    569: NgFuncWritePppFrameLink(Link l, int proto, Mbuf bp)
                    570: {
                    571:     u_int16_t  temp;
                    572: 
                    573:     if (l->joined_bund) {
                    574:        return (NgFuncWritePppFrame(l->bund, l->bundleIndex, proto, bp));
                    575:     }
                    576: 
                    577:     /* Prepend framing */
                    578:     temp = htons(0xff03);
                    579:     bp = mbcopyback(bp, -4, &temp, 2);
                    580:     temp = htons(proto);
                    581:     bp = mbcopyback(bp, 2, &temp, 2);
                    582: 
                    583:     /* Debugging */
                    584:     LogDumpBp(LG_FRAME, bp,
                    585:        "[%s] xmit frame to link proto=0x%04x",
                    586:        l->name, proto);
                    587: 
                    588:     if (l->state != PHYS_STATE_UP) {
                    589:        Log(LG_FRAME, ("[%s] Link: Not ready to send packet", l->name));
                    590:        mbfree(bp);
                    591:        return (-1);
                    592:     }
                    593: 
                    594:     /* Write frame */
                    595:     return NgFuncWriteFrame(gLinksDsock, l->hook, l->name, bp);
                    596: }
                    597: 
                    598: /*
                    599:  * NgFuncWriteFrame()
                    600:  *
                    601:  * Consumes the mbuf.
                    602:  */
                    603: 
                    604: int
                    605: NgFuncWriteFrame(int dsock, const char *hookname, const char *label, Mbuf bp)
                    606: {
                    607:     union {
                    608:         u_char          buf[sizeof(struct sockaddr_ng) + NG_HOOKSIZ];
                    609:        struct sockaddr_ng sa_ng;
                    610:     }                   u;
                    611:     struct sockaddr_ng *ng = &u.sa_ng;
                    612:     int                        rtn;
                    613: 
                    614:     /* Write frame */
                    615:     if (bp == NULL)  
                    616:        return (-1);
                    617: 
                    618:     /* Set dest address */
                    619:     memset(&u.buf, 0, sizeof(u.buf));
                    620:     strlcpy(ng->sg_data, hookname, NG_HOOKSIZ);
                    621:     ng->sg_family = AF_NETGRAPH;
                    622:     ng->sg_len = 3 + strlen(ng->sg_data);
                    623: 
                    624:     rtn = sendto(dsock, MBDATAU(bp), MBLEN(bp),
                    625:        0, (struct sockaddr *)ng, ng->sg_len);
                    626: 
                    627:     /* ENOBUFS can be expected on some links, e.g., ng_pptpgre(4) */
                    628:     if (rtn < 0 && errno != ENOBUFS) {
                    629:        Perror("[%s] error writing len %d frame to %s",
                    630:            label, MBLEN(bp), hookname);
                    631:     }
                    632:     mbfree(bp);
                    633:     return (rtn);
                    634: }
                    635: 
                    636: /*
                    637:  * NgFuncClrStats()
                    638:  *
                    639:  * Clear link or whole bundle statistics
                    640:  */
                    641: 
                    642: int
                    643: NgFuncClrStats(Bund b, u_int16_t linkNum)
                    644: {
                    645:     char       path[NG_PATHSIZ];
                    646: 
                    647:     /* Get stats */
                    648:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    649:     if (NgSendMsg(gLinksCsock, path, 
                    650:        NGM_PPP_COOKIE, NGM_PPP_CLR_LINK_STATS, &linkNum, sizeof(linkNum)) < 0) {
                    651:            Perror("[%s] can't clear stats, link=%d", b->name, linkNum);
                    652:            return (-1);
                    653:     }
                    654:     return(0);
                    655: }
                    656: 
                    657: /*
                    658:  * NgFuncGetStats()
                    659:  *
                    660:  * Get link or whole bundle statistics
                    661:  */
                    662: 
                    663: int
                    664: NgFuncGetStats(Bund b, u_int16_t linkNum, struct ng_ppp_link_stat *statp)
                    665: {
                    666:     union {
                    667:         u_char                 buf[sizeof(struct ng_mesg)
                    668:                                  + sizeof(struct ng_ppp_link_stat)];
                    669:         struct ng_mesg         reply;
                    670:     }                          u;
                    671:     char                       path[NG_PATHSIZ];
                    672: 
                    673:     /* Get stats */
                    674:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    675:     if (NgFuncSendQuery(path, NGM_PPP_COOKIE, NGM_PPP_GET_LINK_STATS,
                    676:       &linkNum, sizeof(linkNum), &u.reply, sizeof(u), NULL) < 0) {
                    677:        Perror("[%s] can't get stats, link=%d", b->name, linkNum);
                    678:        return -1;
                    679:     }
                    680:     if (statp != NULL)
                    681:        memcpy(statp, u.reply.data, sizeof(*statp));
                    682:     return(0);
                    683: }
                    684: 
                    685: #ifdef NG_PPP_STATS64
                    686: /*
                    687:  * NgFuncGetStats64()
                    688:  *
                    689:  * Get 64bit link or whole bundle statistics
                    690:  */
                    691: 
                    692: int
                    693: NgFuncGetStats64(Bund b, u_int16_t linkNum, struct ng_ppp_link_stat64 *statp)
                    694: {
                    695:     union {
                    696:         u_char                 buf[sizeof(struct ng_mesg)
                    697:                                  + sizeof(struct ng_ppp_link_stat64)];
                    698:         struct ng_mesg         reply;
                    699:     }                          u;
                    700:     char                       path[NG_PATHSIZ];
                    701: 
                    702:     /* Get stats */
                    703:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    704:     if (NgFuncSendQuery(path, NGM_PPP_COOKIE, NGM_PPP_GET_LINK_STATS64,
                    705:       &linkNum, sizeof(linkNum), &u.reply, sizeof(u), NULL) < 0) {
                    706:        Perror("[%s] can't get stats, link=%d", b->name, linkNum);
                    707:        return -1;
                    708:     }
                    709:     if (statp != NULL)
                    710:        memcpy(statp, u.reply.data, sizeof(*statp));
                    711:     return(0);
                    712: }
                    713: #endif
                    714: 
                    715: /*
                    716:  * NgFuncErrx()
                    717:  */
                    718: 
                    719: void
                    720: NgFuncErrx(const char *fmt, ...)
                    721: {
                    722:     char       buf[100];
                    723:     va_list    args;
                    724: 
                    725:     va_start(args, fmt);
                    726:     vsnprintf(buf, sizeof(buf), fmt, args);
                    727:     va_end(args);
                    728:     Log(LG_ERR, ("netgraph: %s", buf));
                    729: }
                    730: 
                    731: /*
                    732:  * NgFuncErr()
                    733:  */
                    734: 
                    735: void
                    736: NgFuncErr(const char *fmt, ...)
                    737: {
                    738:     char       buf[100];
                    739:     va_list    args;
                    740: 
                    741:     va_start(args, fmt);
                    742:     vsnprintf(buf, sizeof(buf), fmt, args);
                    743:     va_end(args);
                    744:     Perror("netgraph: %s", buf);
                    745: }
                    746: 
                    747: #ifdef USE_NG_NETFLOW
                    748: /*
                    749:  * NetflowSetCommand()
                    750:  */
                    751:        
                    752: static int
                    753: NetflowSetCommand(Context ctx, int ac, char *av[], void *arg)
                    754: {
                    755:     struct sockaddr_storage *sin;
                    756: 
                    757:     switch ((intptr_t)arg) {
                    758:        case SET_PEER: 
                    759:            if (ac != 2)
                    760:                return (-1);
                    761:            if ((sin = ParseAddrPort(ac, av, ALLOW_IPV4|ALLOW_IPV6)) == NULL)
                    762:                return (-1);
                    763:            gNetflowExport = *sin;
                    764:            break;
                    765:        case SET_SELF:
                    766:            if ((sin = ParseAddrPort(ac, av, ALLOW_IPV4|ALLOW_IPV6)) == NULL)
                    767:                return (-1);
                    768:            gNetflowSource = *sin;
                    769:            break;
                    770:        case SET_TIMEOUTS:
                    771:            if (ac != 2)
                    772:                return (-1);
                    773:            if (atoi(av[0]) <= 0 || atoi(av[1]) <= 0)
                    774:                Error("Bad netflow timeouts \"%s %s\"", av[0], av[1]);
                    775:            gNetflowInactive = atoi(av[0]);
                    776:            gNetflowActive = atoi(av[1]);
                    777:            break;
                    778: #if NGM_NETFLOW_COOKIE >= 1309868867
                    779:        case SET_TEMPLATE:
                    780:            if (ac != 2)
                    781:                return (-1);
                    782:            /*
                    783:             * RFC 3954 clause 7.3
                    784:             * "Both options MUST be configurable by the user on the Exporter."
                    785:             */
                    786:            if (atoi(av[0]) <= 0 || atoi(av[1]) <= 0)
                    787:                Error("Bad netflow v9 template values \"%s %s\"", av[0], av[1]);
                    788:            gNetflowTime = atoi(av[0]);         /* Default 600 */
                    789:            gNetflowPackets = atoi(av[1]);      /* Default 500 */
                    790:            break;
                    791:        case SET_MTU:
                    792:            if (ac != 1)
                    793:                return (-1);
                    794:            if (atoi(av[0]) < MIN_MTU || atoi(av[0]) > MAX_MTU)
                    795:                Error("Bad netflow v9 MTU \"%s\"", av[0]);
                    796:            gNetflowMTU = atoi(av[0]);          /* Default 1500 */
                    797:            break;
                    798:        case SET_VERSION:
                    799:            if (ac != 1)
                    800:                return (-1);
                    801:            if (atoi(av[0]) != 5 && atoi(av[0]) != 9)
                    802:                Error("Bad netflow export version \"%s\"", av[0]);
                    803:            gNetflowVer = atoi(av[0]);          /* Default 5 */
                    804:            break;
                    805: #endif
                    806:        case SET_NODE:
                    807:            if (ac != 1)
                    808:                return (-1);
                    809:            if (strlen(av[0]) == 0 || strlen(av[0]) > 63)
                    810:                Error("Bad netflow node name \"%s\"", av[0]);
                    811:            strlcpy(gNetflowNodeName, av[0], sizeof(gNetflowNodeName));
                    812:            gNetflowNode=TRUE;
                    813:            gNetflowNodeShutdown=FALSE;
                    814:            break;
                    815:        case SET_HOOK:
                    816:            if (ac != 1)
                    817:                return (-1);
                    818:            if (atoi(av[0]) <= 0)
                    819:                Error("Bad netflow hook number \"%s\"", av[0]);
                    820:            gNetflowIface = atoi(av[0])-1;
                    821:            break;
                    822: 
                    823:        default:
                    824:            return (-1);
                    825:     }
                    826: 
                    827:     return (0);
                    828: }
                    829: #endif /* USE_NG_NETFLOW */
                    830: 
                    831: ng_ID_t
                    832: NgGetNodeID(int csock, const char *path)
                    833: {
                    834:     union {
                    835:         u_char          buf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
                    836:        struct ng_mesg  reply;
                    837:     }                   u;
                    838:     struct nodeinfo     *const ni = (struct nodeinfo *)(void *)u.reply.data;
                    839:     
                    840:     if (csock < 0) {
                    841:        if (!gNgStatSock) {
                    842:            char                name[NG_NODESIZ];
                    843:        
                    844:            /* Create a netgraph socket node */
                    845:            snprintf(name, sizeof(name), "mpd%d-stats", gPid);
                    846:            if (NgMkSockNode(name, &gNgStatSock, NULL) < 0) {
                    847:                Perror("NgFuncSendQuery: can't create %s node", NG_SOCKET_NODE_TYPE);
                    848:                return(-1);
                    849:            }
                    850:            (void) fcntl(gNgStatSock, F_SETFD, 1);
                    851:        }
                    852:        csock = gNgStatSock;
                    853:     }
                    854: 
                    855:     if (NgSendMsg(csock, path,
                    856:       NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0)
                    857:         return (0);
                    858:     if (NgRecvMsg(csock, &u.reply, sizeof(u), NULL) < 0)
                    859:        return (0);
                    860:     
                    861:     return (ni->id);
                    862: }
                    863: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>