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

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: #include <netgraph/netflow/netflow.h>
1.1.1.2   misho      48: #if NGM_NETFLOW_COOKIE >= 1309868867
1.1       misho      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
1.1.1.4 ! misho      85:   static int   NetflowSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1       misho      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 },
1.1.1.4 ! misho     112:     { NULL, NULL, NULL, NULL, 0, NULL },
1.1       misho     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
1.1.1.4 ! misho     134:   static uint16_t gNetflowTime = 0;
        !           135:   static uint16_t gNetflowPackets = 0;
        !           136:   static uint16_t gNetflowMTU = 0;
        !           137:   static u_int gNetflowVer = 5;
1.1       misho     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);
1.1.1.4 ! misho     163:        if ((gNetflowNodeID = NgGetNodeID(csock, path)) == 0) {
        !           164:            Perror("NETFLOW: Cannot get %s node id", NG_NETFLOW_NODE_TYPE);
        !           165:            goto fail;
        !           166:        }
1.1       misho     167:        close(csock);
                    168:        return (0);
                    169:     }
                    170: 
                    171:     snprintf(gNetflowNodeName, sizeof(gNetflowNodeName), "mpd%d-nf", gPid);
                    172: 
                    173:     /* Create a global netflow node. */
                    174:     strcpy(mp.type, NG_NETFLOW_NODE_TYPE);
                    175:     strcpy(mp.ourhook, TEMPHOOK);
                    176:     strcpy(mp.peerhook, NG_NETFLOW_HOOK_DATA "0");
                    177:     if (NgSendMsg(csock, ".:",
                    178:       NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                    179:        Perror("NETFLOW: Can't create %s node at \"%s\"->\"%s\"", 
                    180:            mp.type, ".:", mp.ourhook);
                    181:        goto fail;
                    182:     }
                    183:     
                    184:     /* Get new node ID. */
1.1.1.4 ! misho     185:     if ((gNetflowNodeID = NgGetNodeID(csock, TEMPHOOK)) == 0) {
        !           186:        Perror("NETFLOW: Cannot get %s node id", NG_NETFLOW_NODE_TYPE);
        !           187:        goto fail;
        !           188:     }
1.1       misho     189: 
                    190:     /* Set the new node's name. */
                    191:     strcpy(nm.name, gNetflowNodeName);
                    192:     if (NgSendMsg(csock, TEMPHOOK,
                    193:       NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                    194:        Perror("NETFLOW: Can't name %s node", NG_NETFLOW_NODE_TYPE);
                    195:        goto fail;
                    196:     }
                    197: 
                    198:     /* Connect ng_ksocket(4) node for export. */
                    199:     strcpy(mp.type, NG_KSOCKET_NODE_TYPE);
                    200: #if NGM_NETFLOW_COOKIE >= 1309868867
                    201:     if (gNetflowVer == 5) {
                    202: #endif
                    203:        strcpy(mp.ourhook, NG_NETFLOW_HOOK_EXPORT);
                    204: #if NGM_NETFLOW_COOKIE >= 1309868867
                    205:     } else {
                    206:        strcpy(mp.ourhook, NG_NETFLOW_HOOK_EXPORT9);
                    207:     }
                    208: #endif
                    209:     if (gNetflowExport.ss_family==AF_INET6) {
                    210:        snprintf(mp.peerhook, sizeof(mp.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
                    211:     } else {
                    212:         snprintf(mp.peerhook, sizeof(mp.peerhook), "inet/dgram/udp");
                    213:     }
                    214:     snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
                    215:     if (NgSendMsg(csock, path,
                    216:       NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                    217:        Perror("NETFLOW: Can't create %s node at \"%s\"->\"%s\"",
                    218:            mp.type, path, mp.ourhook);
                    219:        goto fail;
                    220:     }
                    221: 
                    222:     /* Configure timeouts for ng_netflow(4). */
                    223:     if (gNetflowInactive != 0 && gNetflowActive != 0) {
                    224:        struct ng_netflow_settimeouts nf_settime;
                    225: 
                    226:        nf_settime.inactive_timeout = gNetflowInactive;
                    227:        nf_settime.active_timeout = gNetflowActive;
                    228: 
                    229:        if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
                    230:          NGM_NETFLOW_SETTIMEOUTS, &nf_settime, sizeof(nf_settime)) < 0) {
                    231:            Perror("NETFLOW: Can't set timeouts on netflow %s node",
                    232:                NG_NETFLOW_NODE_TYPE);
                    233:            goto fail2;
                    234:        }
                    235:     }
                    236: 
                    237: #if NGM_NETFLOW_COOKIE >= 1309868867
                    238:     if (gNetflowTime != 0 && gNetflowPackets != 0) {
                    239:        struct ng_netflow_settemplate nf_settempl;
                    240: 
                    241:        nf_settempl.time = gNetflowTime;
                    242:        nf_settempl.packets = gNetflowPackets;
                    243:        if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
                    244:          NGM_NETFLOW_SETTEMPLATE, &nf_settempl, sizeof(nf_settempl)) < 0) {
                    245:            Perror("NETFLOW: Can't set NetFlow v9 template on netflow %s node",
                    246:                NG_NETFLOW_NODE_TYPE);
                    247:            goto fail2;
                    248:        }
                    249:     }
                    250: 
                    251:     if (gNetflowMTU != 0) {
                    252:        struct ng_netflow_setmtu nf_setmtu;
                    253: 
                    254:        nf_setmtu.mtu = gNetflowMTU;
                    255:        if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
                    256:          NGM_NETFLOW_SETMTU, &nf_setmtu, sizeof(nf_setmtu)) < 0) {
                    257:            Perror("NETFLOW: Can't set NetFlow v9 MTU on netflow %s node",
                    258:                NG_NETFLOW_NODE_TYPE);
                    259:          goto fail2;
                    260:        }
                    261:     }
                    262: #endif
                    263: 
                    264:     /* Configure export destination and source on ng_ksocket(4). */
                    265: #if NGM_NETFLOW_COOKIE >= 1309868867
                    266:     if (gNetflowVer == 5) {
                    267: #endif
                    268:        strlcat(path, NG_NETFLOW_HOOK_EXPORT, sizeof(path));
                    269: #if NGM_NETFLOW_COOKIE >= 1309868867
                    270:     } else {
                    271:        strlcat(path, NG_NETFLOW_HOOK_EXPORT9, sizeof(path));
                    272:     }
                    273: #endif
                    274:     if (gNetflowSource.ss_len != 0) {
                    275:        if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
                    276:          NGM_KSOCKET_BIND, &gNetflowSource, sizeof(gNetflowSource)) < 0) {
                    277:            Perror("NETFLOW: Can't bind export %s node", NG_KSOCKET_NODE_TYPE);
                    278:            goto fail2;
                    279:        }
                    280:     }
                    281:     if (gNetflowExport.ss_len != 0) {
                    282:        if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
                    283:          NGM_KSOCKET_CONNECT, &gNetflowExport, sizeof(gNetflowExport)) < 0) {
                    284:            Perror("NETFLOW: Can't connect export %s node", NG_KSOCKET_NODE_TYPE);
                    285:            goto fail2;
                    286:        }
                    287:     }
                    288: 
                    289:     /* Set the new node's name. */
                    290:     snprintf(nm.name, sizeof(nm.name), "mpd%d-nfso", gPid);
                    291:     if (NgSendMsg(csock, path,
                    292:       NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                    293:        Perror("NETFLOW: Can't name %s node", NG_KSOCKET_NODE_TYPE);
                    294:        goto fail2;
                    295:     }
                    296: 
                    297:     /* Disconnect temporary hook. */
                    298:     memset(&rm, 0, sizeof(rm));
                    299:     strncpy(rm.ourhook, TEMPHOOK, sizeof(rm.ourhook));
                    300:     if (NgSendMsg(csock, ".:",
                    301:       NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
                    302:        Perror("can't remove hook %s", TEMPHOOK);
                    303:        goto fail2;
                    304:     }
                    305:     gNetflowNode = TRUE;
                    306:     close(csock);
                    307: 
                    308:     return (0);
                    309: fail2:
                    310:     snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
                    311:     NgFuncShutdownNode(csock, "netflow", path);
                    312: fail:
                    313:     gNetflowNodeID = 0;
                    314:     close(csock);
                    315:     return (-1);
                    316: }
                    317: #endif
                    318: 
                    319: /*
                    320:  * NgFuncCreateIface()
                    321:  *
                    322:  * Create a new netgraph interface.
                    323:  */
                    324: 
                    325: int
                    326: NgFuncCreateIface(Bund b, char *buf, int max)
                    327: {
                    328:     union {
                    329:         u_char         buf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
                    330:         struct ng_mesg reply;
                    331:     }                  u;
                    332:     struct nodeinfo    *const ni = (struct nodeinfo *)(void *)u.reply.data;
                    333:     struct ngm_rmhook  rm;
                    334:     struct ngm_mkpeer  mp;
                    335:     int                        rtn = 0;
                    336: 
                    337:     /* Create iface node (as a temporary peer of the socket node) */
                    338:     strcpy(mp.type, NG_IFACE_NODE_TYPE);
                    339:     strcpy(mp.ourhook, TEMPHOOK);
                    340:     strcpy(mp.peerhook, NG_IFACE_HOOK_INET);
                    341:     if (NgSendMsg(gLinksCsock, ".:",
                    342:       NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                    343:        Log(LG_ERR, ("[%s] can't create %s node at \"%s\"->\"%s\": %s %d",
                    344:            b->name, NG_IFACE_NODE_TYPE, ".:", mp.ourhook, strerror(errno), gLinksCsock));
                    345:        return(-1);
                    346:     }
                    347: 
                    348:     /* Get the new node's name */
                    349:     if (NgSendMsg(gLinksCsock, TEMPHOOK,
                    350:       NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0) {
                    351:        Perror("[%s] %s", b->name, "NGM_NODEINFO");
                    352:        rtn = -1;
                    353:        goto done;
                    354:     }
                    355:     if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0) {
                    356:        Perror("[%s] reply from %s", b->name, NG_IFACE_NODE_TYPE);
                    357:        rtn = -1;
                    358:        goto done;
                    359:     }
                    360:     strlcpy(buf, ni->name, max);
                    361: 
                    362: done:
                    363:     /* Disconnect temporary hook */
                    364:     strcpy(rm.ourhook, TEMPHOOK);
                    365:     if (NgSendMsg(gLinksCsock, ".:",
                    366:       NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
                    367:        Perror("[%s] can't remove hook %s", b->name, TEMPHOOK);
                    368:        rtn = -1;
                    369:     }
                    370: 
                    371:     /* Done */
                    372:     return(rtn);
                    373: }
                    374: 
                    375: /*
                    376:  * NgFuncShutdownGlobal()
                    377:  *
                    378:  * Shutdown nodes, that are shared between bundles.
                    379:  */
                    380: 
                    381: void
                    382: NgFuncShutdownGlobal(void)
                    383: {
                    384: #ifdef USE_NG_NETFLOW
                    385:     char       path[NG_PATHSIZ];
                    386:     int                csock;
                    387: 
                    388:     if (gNetflowNode == FALSE || gNetflowNodeShutdown==FALSE)
                    389:        return;
                    390: 
                    391:     /* Create a netgraph socket node */
                    392:     if (NgMkSockNode(NULL, &csock, NULL) < 0) {
                    393:        Perror("NgFuncShutdownGlobal: can't create %s node", NG_SOCKET_NODE_TYPE);
                    394:        return;
                    395:     }
                    396: 
                    397:     snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
                    398:     NgFuncShutdownNode(csock, "netflow", path);
                    399:     
                    400:     close(csock);
                    401: #endif
                    402: }
                    403: 
                    404: /*
                    405:  * NgFuncShutdownNode()
                    406:  */
                    407: 
                    408: int
                    409: NgFuncShutdownNode(int csock, const char *label, const char *path)
                    410: {
                    411:     int rtn, retry = 10, delay = 1000;
                    412: 
                    413: retry:
                    414:     if ((rtn = NgSendMsg(csock, path,
                    415:       NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0)) < 0) {
                    416:        if (errno == ENOBUFS && retry > 0) {
                    417:            Log(LG_ERR, ("[%s] shutdown \"%s\": %s, retrying...",
                    418:              label, path, strerror(errno)));
                    419:            usleep(delay);
                    420:            retry--;
                    421:            delay *= 2;
                    422:            goto retry;
                    423:        }
                    424:        if (errno != ENOENT) {
                    425:            Perror("[%s] can't shutdown \"%s\"", label, path);
                    426:        }
                    427:     }
                    428:     return(rtn);
                    429: }
                    430: 
                    431: /*
                    432:  * NgFuncSetConfig()
                    433:  */
                    434: 
                    435: void
                    436: NgFuncSetConfig(Bund b)
                    437: {
                    438:     char       path[NG_PATHSIZ];
                    439:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    440:     if (NgSendMsg(gLinksCsock, path, NGM_PPP_COOKIE,
                    441:            NGM_PPP_SET_CONFIG, &b->pppConfig, sizeof(b->pppConfig)) < 0) {
                    442:        Perror("[%s] can't config %s", b->name, path);
                    443:        DoExit(EX_ERRDEAD);
                    444:     }
                    445: }
                    446: 
                    447: /*
                    448:  * NgFuncSendQuery()
                    449:  */
                    450: 
                    451: int
                    452: NgFuncSendQuery(const char *path, int cookie, int cmd, const void *args,
                    453:        size_t arglen, struct ng_mesg *rbuf, size_t replen, char *raddr)
                    454: {
                    455: 
                    456:     if (!gNgStatSock) {
                    457:        char            name[NG_NODESIZ];
                    458:        
                    459:        /* Create a netgraph socket node */
                    460:        snprintf(name, sizeof(name), "mpd%d-stats", gPid);
                    461:        if (NgMkSockNode(name, &gNgStatSock, NULL) < 0) {
                    462:            Perror("NgFuncSendQuery: can't create %s node", NG_SOCKET_NODE_TYPE);
                    463:            return(-1);
                    464:        }
                    465:        (void) fcntl(gNgStatSock, F_SETFD, 1);
                    466:     }
                    467: 
                    468:     /* Send message */
1.1.1.2   misho     469:     if (NgSendMsg(gNgStatSock, path, cookie, cmd, args, arglen) < 0) {
                    470:        Perror("NgFuncSendQuery: can't send message");
1.1       misho     471:        return (-1);
1.1.1.2   misho     472:     }
1.1       misho     473: 
                    474:     /* Read message */
                    475:     if (NgRecvMsg(gNgStatSock, rbuf, replen, raddr) < 0) {
                    476:        Perror("NgFuncSendQuery: can't read unexpected message");
                    477:        return (-1);
                    478:     }
                    479: 
                    480:     return (0);
                    481: }
                    482: 
                    483: /*
                    484:  * NgFuncConnect()
                    485:  */
                    486: 
                    487: int
                    488: NgFuncConnect(int csock, char *label, const char *path, const char *hook,
                    489:        const char *path2, const char *hook2)
                    490: {
                    491:     struct ngm_connect cn;
                    492: 
                    493:     strlcpy(cn.path, path2, sizeof(cn.path));
                    494:     strlcpy(cn.ourhook, hook, sizeof(cn.ourhook));
                    495:     strlcpy(cn.peerhook, hook2, sizeof(cn.peerhook));
                    496:     if (NgSendMsg(csock, path,
                    497:       NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    498:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    499:            label, path, hook, path2, hook2);
                    500:        return(-1);
                    501:     }
                    502:     return(0);
                    503: }
                    504: 
                    505: /*
                    506:  * NgFuncDisconnect()
                    507:  */
                    508: 
                    509: int
                    510: NgFuncDisconnect(int csock, char *label, const char *path, const char *hook)
                    511: {
                    512:     struct ngm_rmhook  rm;
                    513:     int                retry = 10, delay = 1000;
                    514: 
                    515:     /* Disconnect hook */
                    516:     memset(&rm, 0, sizeof(rm));
                    517:     strlcpy(rm.ourhook, hook, sizeof(rm.ourhook));
                    518: retry:
                    519:     if (NgSendMsg(csock, path,
                    520:       NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
                    521:        if (errno == ENOBUFS && retry > 0) {
                    522:            Log(LG_ERR, ("[%s] remove hook %s from node \"%s\": %s, retrying...",
                    523:              label, hook, path, strerror(errno)));
                    524:            usleep(delay);
                    525:            retry--;
                    526:            delay *= 2;
                    527:            goto retry;
                    528:        }
                    529:        Perror("[%s] can't remove hook %s from node \"%s\"", label, hook, path);
                    530:        return(-1);
                    531:     }
                    532:     return(0);
                    533: }
                    534: 
                    535: /*
                    536:  * NgFuncWritePppFrame()
                    537:  *
                    538:  * Consumes the mbuf.
                    539:  */
                    540: 
                    541: int
                    542: NgFuncWritePppFrame(Bund b, int linkNum, int proto, Mbuf bp)
                    543: {
                    544:     u_int16_t  temp;
                    545: 
                    546:     /* Prepend ppp node bypass header */
                    547:     temp = htons(linkNum);
                    548:     bp = mbcopyback(bp, -4, &temp, 2);
                    549:     temp = htons(proto);
                    550:     bp = mbcopyback(bp, 2, &temp, 2);
                    551: 
                    552:     /* Debugging */
                    553:     LogDumpBp(LG_FRAME, bp,
                    554:        "[%s] xmit bypass frame link=%d proto=0x%04x",
                    555:        b->name, (int16_t)linkNum, proto);
                    556: 
                    557:     if ((linkNum == NG_PPP_BUNDLE_LINKNUM && b->n_up == 0) ||
                    558:        (linkNum != NG_PPP_BUNDLE_LINKNUM &&
                    559:            (b->links[linkNum] == NULL ||
                    560:            b->links[linkNum]->state != PHYS_STATE_UP))) {
                    561:        Log(LG_FRAME, ("[%s] Bundle: No links ready to send packet", b->name));
                    562:        mbfree(bp);
                    563:        return (-1);
                    564:     }
                    565: 
                    566:     /* Write frame */
                    567:     return NgFuncWriteFrame(gLinksDsock, b->hook, b->name, bp);
                    568: }
                    569: 
                    570: /*
                    571:  * NgFuncWritePppFrameLink()
                    572:  *
                    573:  * Consumes the mbuf.
                    574:  */
                    575: 
                    576: int
                    577: NgFuncWritePppFrameLink(Link l, int proto, Mbuf bp)
                    578: {
                    579:     u_int16_t  temp;
                    580: 
                    581:     if (l->joined_bund) {
                    582:        return (NgFuncWritePppFrame(l->bund, l->bundleIndex, proto, bp));
                    583:     }
                    584: 
                    585:     /* Prepend framing */
                    586:     temp = htons(0xff03);
                    587:     bp = mbcopyback(bp, -4, &temp, 2);
                    588:     temp = htons(proto);
                    589:     bp = mbcopyback(bp, 2, &temp, 2);
                    590: 
                    591:     /* Debugging */
                    592:     LogDumpBp(LG_FRAME, bp,
                    593:        "[%s] xmit frame to link proto=0x%04x",
                    594:        l->name, proto);
                    595: 
                    596:     if (l->state != PHYS_STATE_UP) {
                    597:        Log(LG_FRAME, ("[%s] Link: Not ready to send packet", l->name));
                    598:        mbfree(bp);
                    599:        return (-1);
                    600:     }
                    601: 
                    602:     /* Write frame */
                    603:     return NgFuncWriteFrame(gLinksDsock, l->hook, l->name, bp);
                    604: }
                    605: 
                    606: /*
                    607:  * NgFuncWriteFrame()
                    608:  *
                    609:  * Consumes the mbuf.
                    610:  */
                    611: 
                    612: int
                    613: NgFuncWriteFrame(int dsock, const char *hookname, const char *label, Mbuf bp)
                    614: {
                    615:     union {
                    616:         u_char          buf[sizeof(struct sockaddr_ng) + NG_HOOKSIZ];
                    617:        struct sockaddr_ng sa_ng;
                    618:     }                   u;
                    619:     struct sockaddr_ng *ng = &u.sa_ng;
                    620:     int                        rtn;
                    621: 
                    622:     /* Write frame */
                    623:     if (bp == NULL)  
                    624:        return (-1);
                    625: 
                    626:     /* Set dest address */
                    627:     memset(&u.buf, 0, sizeof(u.buf));
                    628:     strlcpy(ng->sg_data, hookname, NG_HOOKSIZ);
                    629:     ng->sg_family = AF_NETGRAPH;
                    630:     ng->sg_len = 3 + strlen(ng->sg_data);
                    631: 
                    632:     rtn = sendto(dsock, MBDATAU(bp), MBLEN(bp),
                    633:        0, (struct sockaddr *)ng, ng->sg_len);
                    634: 
                    635:     /* ENOBUFS can be expected on some links, e.g., ng_pptpgre(4) */
                    636:     if (rtn < 0 && errno != ENOBUFS) {
                    637:        Perror("[%s] error writing len %d frame to %s",
1.1.1.3   misho     638:            label, (int)MBLEN(bp), hookname);
1.1       misho     639:     }
                    640:     mbfree(bp);
                    641:     return (rtn);
                    642: }
                    643: 
                    644: /*
                    645:  * NgFuncClrStats()
                    646:  *
                    647:  * Clear link or whole bundle statistics
                    648:  */
                    649: 
                    650: int
                    651: NgFuncClrStats(Bund b, u_int16_t linkNum)
                    652: {
                    653:     char       path[NG_PATHSIZ];
                    654: 
                    655:     /* Get stats */
                    656:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    657:     if (NgSendMsg(gLinksCsock, path, 
                    658:        NGM_PPP_COOKIE, NGM_PPP_CLR_LINK_STATS, &linkNum, sizeof(linkNum)) < 0) {
                    659:            Perror("[%s] can't clear stats, link=%d", b->name, linkNum);
                    660:            return (-1);
                    661:     }
                    662:     return(0);
                    663: }
                    664: 
1.1.1.4 ! misho     665: #ifndef NG_PPP_STATS64
        !           666: 
1.1       misho     667: /*
                    668:  * NgFuncGetStats()
                    669:  *
                    670:  * Get link or whole bundle statistics
                    671:  */
                    672: 
                    673: int
                    674: NgFuncGetStats(Bund b, u_int16_t linkNum, struct ng_ppp_link_stat *statp)
                    675: {
                    676:     union {
                    677:         u_char                 buf[sizeof(struct ng_mesg)
                    678:                                  + sizeof(struct ng_ppp_link_stat)];
                    679:         struct ng_mesg         reply;
                    680:     }                          u;
                    681:     char                       path[NG_PATHSIZ];
                    682: 
                    683:     /* Get stats */
                    684:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    685:     if (NgFuncSendQuery(path, NGM_PPP_COOKIE, NGM_PPP_GET_LINK_STATS,
                    686:       &linkNum, sizeof(linkNum), &u.reply, sizeof(u), NULL) < 0) {
                    687:        Perror("[%s] can't get stats, link=%d", b->name, linkNum);
                    688:        return -1;
                    689:     }
                    690:     if (statp != NULL)
                    691:        memcpy(statp, u.reply.data, sizeof(*statp));
                    692:     return(0);
                    693: }
                    694: 
1.1.1.4 ! misho     695: #else
1.1       misho     696: /*
                    697:  * NgFuncGetStats64()
                    698:  *
                    699:  * Get 64bit link or whole bundle statistics
                    700:  */
                    701: 
                    702: int
                    703: NgFuncGetStats64(Bund b, u_int16_t linkNum, struct ng_ppp_link_stat64 *statp)
                    704: {
                    705:     union {
                    706:         u_char                 buf[sizeof(struct ng_mesg)
                    707:                                  + sizeof(struct ng_ppp_link_stat64)];
                    708:         struct ng_mesg         reply;
                    709:     }                          u;
                    710:     char                       path[NG_PATHSIZ];
                    711: 
                    712:     /* Get stats */
                    713:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                    714:     if (NgFuncSendQuery(path, NGM_PPP_COOKIE, NGM_PPP_GET_LINK_STATS64,
                    715:       &linkNum, sizeof(linkNum), &u.reply, sizeof(u), NULL) < 0) {
                    716:        Perror("[%s] can't get stats, link=%d", b->name, linkNum);
                    717:        return -1;
                    718:     }
                    719:     if (statp != NULL)
                    720:        memcpy(statp, u.reply.data, sizeof(*statp));
                    721:     return(0);
                    722: }
                    723: #endif
                    724: 
                    725: /*
                    726:  * NgFuncErrx()
                    727:  */
                    728: 
                    729: void
                    730: NgFuncErrx(const char *fmt, ...)
                    731: {
                    732:     char       buf[100];
                    733:     va_list    args;
                    734: 
                    735:     va_start(args, fmt);
                    736:     vsnprintf(buf, sizeof(buf), fmt, args);
                    737:     va_end(args);
                    738:     Log(LG_ERR, ("netgraph: %s", buf));
                    739: }
                    740: 
                    741: /*
                    742:  * NgFuncErr()
                    743:  */
                    744: 
                    745: void
                    746: NgFuncErr(const char *fmt, ...)
                    747: {
                    748:     char       buf[100];
                    749:     va_list    args;
                    750: 
                    751:     va_start(args, fmt);
                    752:     vsnprintf(buf, sizeof(buf), fmt, args);
                    753:     va_end(args);
                    754:     Perror("netgraph: %s", buf);
                    755: }
                    756: 
                    757: #ifdef USE_NG_NETFLOW
                    758: /*
                    759:  * NetflowSetCommand()
                    760:  */
                    761:        
                    762: static int
1.1.1.4 ! misho     763: NetflowSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     764: {
                    765:     struct sockaddr_storage *sin;
                    766: 
                    767:     switch ((intptr_t)arg) {
                    768:        case SET_PEER: 
                    769:            if (ac != 2)
                    770:                return (-1);
                    771:            if ((sin = ParseAddrPort(ac, av, ALLOW_IPV4|ALLOW_IPV6)) == NULL)
                    772:                return (-1);
                    773:            gNetflowExport = *sin;
                    774:            break;
                    775:        case SET_SELF:
1.1.1.3   misho     776:            if (ac != 1 && ac != 2)
                    777:                return (-1);
1.1       misho     778:            if ((sin = ParseAddrPort(ac, av, ALLOW_IPV4|ALLOW_IPV6)) == NULL)
                    779:                return (-1);
                    780:            gNetflowSource = *sin;
                    781:            break;
                    782:        case SET_TIMEOUTS:
                    783:            if (ac != 2)
                    784:                return (-1);
                    785:            if (atoi(av[0]) <= 0 || atoi(av[1]) <= 0)
                    786:                Error("Bad netflow timeouts \"%s %s\"", av[0], av[1]);
                    787:            gNetflowInactive = atoi(av[0]);
                    788:            gNetflowActive = atoi(av[1]);
                    789:            break;
                    790: #if NGM_NETFLOW_COOKIE >= 1309868867
                    791:        case SET_TEMPLATE:
                    792:            if (ac != 2)
                    793:                return (-1);
                    794:            /*
                    795:             * RFC 3954 clause 7.3
                    796:             * "Both options MUST be configurable by the user on the Exporter."
                    797:             */
                    798:            if (atoi(av[0]) <= 0 || atoi(av[1]) <= 0)
                    799:                Error("Bad netflow v9 template values \"%s %s\"", av[0], av[1]);
                    800:            gNetflowTime = atoi(av[0]);         /* Default 600 */
                    801:            gNetflowPackets = atoi(av[1]);      /* Default 500 */
                    802:            break;
                    803:        case SET_MTU:
                    804:            if (ac != 1)
                    805:                return (-1);
1.1.1.4 ! misho     806:            if (atoi(av[0]) < (int)MIN_MTU || atoi(av[0]) > (int)MAX_MTU)
1.1       misho     807:                Error("Bad netflow v9 MTU \"%s\"", av[0]);
                    808:            gNetflowMTU = atoi(av[0]);          /* Default 1500 */
                    809:            break;
                    810:        case SET_VERSION:
                    811:            if (ac != 1)
                    812:                return (-1);
                    813:            if (atoi(av[0]) != 5 && atoi(av[0]) != 9)
                    814:                Error("Bad netflow export version \"%s\"", av[0]);
                    815:            gNetflowVer = atoi(av[0]);          /* Default 5 */
                    816:            break;
                    817: #endif
                    818:        case SET_NODE:
                    819:            if (ac != 1)
                    820:                return (-1);
                    821:            if (strlen(av[0]) == 0 || strlen(av[0]) > 63)
                    822:                Error("Bad netflow node name \"%s\"", av[0]);
                    823:            strlcpy(gNetflowNodeName, av[0], sizeof(gNetflowNodeName));
                    824:            gNetflowNode=TRUE;
                    825:            gNetflowNodeShutdown=FALSE;
                    826:            break;
                    827:        case SET_HOOK:
                    828:            if (ac != 1)
                    829:                return (-1);
1.1.1.3   misho     830:            if (atoi(av[0]) <= 0 || atoi(av[0]) >= NG_NETFLOW_MAXIFACES)
1.1       misho     831:                Error("Bad netflow hook number \"%s\"", av[0]);
                    832:            gNetflowIface = atoi(av[0])-1;
                    833:            break;
                    834: 
                    835:        default:
                    836:            return (-1);
                    837:     }
                    838: 
                    839:     return (0);
                    840: }
1.1.1.2   misho     841: 
                    842: /*
                    843:  * ShowNetflow()
                    844:  *
                    845:  * Show state of a Netflow
                    846:  */
                    847: 
                    848: int
1.1.1.4 ! misho     849: ShowNetflow(Context ctx, int ac, const char *const av[], const void *arg)
1.1.1.2   misho     850: {
                    851:     struct u_addr addr;
                    852:     in_port_t port;
                    853:     char buf[64];
                    854:     char path[NG_PATHSIZ];
                    855:     union {
                    856:         u_char buf[sizeof(struct ng_mesg) + sizeof(struct ng_netflow_info)];
                    857:         struct ng_mesg reply;
                    858:     } u;
                    859:     struct ng_netflow_info *const ni = \
                    860:         (struct ng_netflow_info *)(void *)u.reply.data;
                    861: #ifdef NGM_NETFLOW_V9_COOKIE
                    862:     union {
                    863:         u_char buf[sizeof(struct ng_mesg) + sizeof(struct ng_netflow_v9info)];
                    864:         struct ng_mesg reply;
                    865:     } uv9;
                    866:     struct ng_netflow_v9info *const niv9 = \
                    867:         (struct ng_netflow_v9info *)(void *)uv9.reply.data;
                    868: #endif /* NGM_NETFLOW_V9_COOKIE */
                    869: 
1.1.1.4 ! misho     870:     (void)ac;
        !           871:     (void)av;
        !           872:     (void)arg;
        !           873: 
1.1.1.2   misho     874:     if (gNetflowNodeID>0) {
                    875:         snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
                    876:         if (NgFuncSendQuery(path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_INFO,
                    877:         NULL, 0, &u.reply, sizeof(u), NULL) < 0)
                    878:             return(-7);
                    879: #ifdef NGM_NETFLOW_V9_COOKIE
                    880:         if (NgFuncSendQuery(path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_V9INFO,
                    881:         NULL, 0, &uv9.reply, sizeof(uv9), NULL) < 0)
                    882:             return(-7);
                    883: #endif /* NGM_NETFLOW_V9_COOKIE */
                    884:     }
                    885: 
                    886:     Printf("Netflow status:\r\n");
                    887:     Printf("\tNode created   : %s\r\n", gNetflowNodeID ? "Yes" : "No");
                    888:     Printf("Netflow settings:\r\n");
                    889:     Printf("\tNode name      : %s\r\n", gNetflowNodeName);
                    890:     Printf("\tInitial hook   : %d\r\n", gNetflowIface);
                    891:     Printf("\tTimeouts, sec:\r\n");
1.1.1.3   misho     892:     Printf("\t  Active       : %u\r\n",
1.1.1.2   misho     893:         (gNetflowNodeID>0) ? ni->nfinfo_act_t :
                    894:         (gNetflowActive ? gNetflowActive : ACTIVE_TIMEOUT));
1.1.1.3   misho     895:     Printf("\t  Inactive     : %u\r\n",
1.1.1.2   misho     896:         (gNetflowNodeID>0) ? ni->nfinfo_inact_t :
                    897:         (gNetflowInactive ? gNetflowInactive : INACTIVE_TIMEOUT));
                    898:     sockaddrtou_addr(&gNetflowExport, &addr, &port);
                    899:     Printf("\tExport address : %s port %d\r\n",
                    900:         u_addrtoa(&addr, buf, sizeof(buf)), (int)port);
                    901:     sockaddrtou_addr(&gNetflowSource, &addr, &port);
                    902:     Printf("\tSource address : %s port %d\r\n",
                    903:         u_addrtoa(&addr, buf, sizeof(buf)), (int)port);
                    904: #if NGM_NETFLOW_COOKIE >= 1309868867
                    905:     Printf("\tExport version : v%d\r\n", gNetflowVer);
                    906:     Printf("Netflow v9 configuration:\r\n");
                    907:     Printf("\tTemplate:\r\n");
                    908: #ifdef NGM_NETFLOW_V9_COOKIE
                    909:     Printf("\t  Time         : %d\r\n",
                    910:         (gNetflowNodeID>0) ? niv9->templ_time :
                    911:         (gNetflowTime ? gNetflowTime : NETFLOW_V9_MAX_TIME_TEMPL));
                    912:     Printf("\t  Packets      : %d\r\n",
                    913:         (gNetflowNodeID>0) ? niv9->templ_packets :
                    914:         (gNetflowPackets ? gNetflowPackets : NETFLOW_V9_MAX_PACKETS_TEMPL));
                    915:     Printf("\tNetflow v9 MTU : %d\r\n",
                    916:         (gNetflowNodeID>0) ? niv9->mtu :
                    917:         (gNetflowMTU ? gNetflowMTU : BASE_MTU));
                    918: #else
                    919:     Printf("\t  Time         : %d\r\n",
                    920:         gNetflowTime ? gNetflowTime : NETFLOW_V9_MAX_TIME_TEMPL);
                    921:     Printf("\t  Packets      : %d\r\n",
                    922:         gNetflowPackets ? gNetflowPackets : NETFLOW_V9_MAX_PACKETS_TEMPL);
                    923:     Printf("\tNetflow v9 MTU : %d\r\n",
                    924:         gNetflowMTU ? gNetflowMTU : BASE_MTU);
                    925: #endif /* NGM_NETFLOW_V9_COOKIE */
                    926: #endif
                    927:     if (gNetflowNodeID>0) {
                    928:         Printf("Traffic stats:\r\n");
1.1.1.3   misho     929: #if NGM_NETFLOW_COOKIE >= 1365756954
                    930:         Printf("\tAccounted IPv4 octets  : %llu\r\n", (unsigned long long)ni->nfinfo_bytes);
                    931:         Printf("\tAccounted IPv4 packets : %llu\r\n", (unsigned long long)ni->nfinfo_packets);
                    932:         Printf("\tAccounted IPv6 octets  : %llu\r\n", (unsigned long long)ni->nfinfo_bytes6);
                    933:         Printf("\tAccounted IPv6 packets : %llu\r\n", (unsigned long long)ni->nfinfo_packets6);
                    934:         Printf("\tSkipped IPv4 octets    : %llu\r\n", (unsigned long long)ni->nfinfo_sbytes);
                    935:         Printf("\tSkipped IPv4 packets   : %llu\r\n", (unsigned long long)ni->nfinfo_spackets);
                    936:         Printf("\tSkipped IPv6 octets    : %llu\r\n", (unsigned long long)ni->nfinfo_sbytes6);
                    937:         Printf("\tSkipped IPv6 packets   : %llu\r\n", (unsigned long long)ni->nfinfo_spackets6);
                    938:         Printf("\tActive expiries        : %llu\r\n", (unsigned long long)ni->nfinfo_act_exp);
                    939:         Printf("\tInactive expiries      : %llu\r\n", (unsigned long long)ni->nfinfo_inact_exp);
                    940:         Printf("\tUsed IPv4 cache records: %u\r\n", ni->nfinfo_used);
                    941:         Printf("\tUsed IPv6 cache records: %u\r\n", ni->nfinfo_used6);
                    942:         Printf("\tFailed allocations     : %u\r\n", ni->nfinfo_alloc_failed);
                    943:         Printf("\tFailed v5 export       : %u\r\n", ni->nfinfo_export_failed);
                    944:         Printf("\tFailed v9 export       : %u\r\n", ni->nfinfo_export9_failed);
                    945:         Printf("\tRallocated mbufs       : %u\r\n", ni->nfinfo_realloc_mbuf);
                    946:         Printf("\tFibs allocated         : %u\r\n", ni->nfinfo_alloc_fibs);
                    947: #else /* NGM_NETFLOW_COOKIE >= 1365756954 */
1.1.1.2   misho     948:         Printf("\tAccounted IPv4 octets  : %llu\r\n", (unsigned long long)ni->nfinfo_bytes);
1.1.1.3   misho     949:         Printf("\tAccounted IPv4 packets : %u\r\n", ni->nfinfo_packets);
1.1.1.2   misho     950: #if NGM_NETFLOW_COOKIE >= 1309868867
                    951:         Printf("\tAccounted IPv6 octets  : %llu\r\n", (unsigned long long)ni->nfinfo_bytes6);
1.1.1.3   misho     952:         Printf("\tAccounted IPv6 packets : %u\r\n", ni->nfinfo_packets6);
1.1.1.2   misho     953:         Printf("\tSkipped IPv4 octets    : %llu\r\n", (unsigned long long)ni->nfinfo_sbytes);
1.1.1.3   misho     954:         Printf("\tSkipped IPv4 packets   : %u\r\n", ni->nfinfo_spackets);
1.1.1.2   misho     955:         Printf("\tSkipped IPv6 octets    : %llu\r\n", (unsigned long long)ni->nfinfo_sbytes6);
1.1.1.3   misho     956:         Printf("\tSkipped IPv6 packets   : %u\r\n", ni->nfinfo_spackets6);
1.1.1.2   misho     957: #endif
1.1.1.3   misho     958:         Printf("\tUsed IPv4 cache records: %u\r\n", ni->nfinfo_used);
1.1.1.2   misho     959: #if NGM_NETFLOW_COOKIE >= 1309868867
1.1.1.3   misho     960:         Printf("\tUsed IPv6 cache records: %u\r\n", ni->nfinfo_used6);
1.1.1.2   misho     961: #endif
1.1.1.3   misho     962:         Printf("\tFailed allocations     : %u\r\n", ni->nfinfo_alloc_failed);
                    963:         Printf("\tFailed v5 export       : %u\r\n", ni->nfinfo_export_failed);
1.1.1.2   misho     964: #if NGM_NETFLOW_COOKIE >= 1309868867
1.1.1.3   misho     965:         Printf("\tFailed v9 export       : %u\r\n", ni->nfinfo_export9_failed);
                    966:         Printf("\tRallocated mbufs       : %u\r\n", ni->nfinfo_realloc_mbuf);
                    967:         Printf("\tFibs allocated         : %u\r\n", ni->nfinfo_alloc_fibs);
1.1.1.2   misho     968: #endif
1.1.1.3   misho     969:         Printf("\tActive expiries        : %u\r\n", ni->nfinfo_act_exp);
                    970:         Printf("\tInactive expiries      : %u\r\n", ni->nfinfo_inact_exp);
                    971: #endif /* NGM_NETFLOW_COOKIE >= 1365756954 */
1.1.1.2   misho     972:     }
                    973:     return(0);
                    974: }
1.1       misho     975: #endif /* USE_NG_NETFLOW */
                    976: 
                    977: ng_ID_t
                    978: NgGetNodeID(int csock, const char *path)
                    979: {
                    980:     union {
                    981:         u_char          buf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
                    982:        struct ng_mesg  reply;
                    983:     }                   u;
                    984:     struct nodeinfo     *const ni = (struct nodeinfo *)(void *)u.reply.data;
                    985:     
                    986:     if (csock < 0) {
                    987:        if (!gNgStatSock) {
                    988:            char                name[NG_NODESIZ];
                    989:        
                    990:            /* Create a netgraph socket node */
                    991:            snprintf(name, sizeof(name), "mpd%d-stats", gPid);
                    992:            if (NgMkSockNode(name, &gNgStatSock, NULL) < 0) {
1.1.1.4 ! misho     993:                Perror("NgMkSockNode: can't create %s node",
        !           994:                     NG_SOCKET_NODE_TYPE);
        !           995:                return (0);
1.1       misho     996:            }
                    997:            (void) fcntl(gNgStatSock, F_SETFD, 1);
                    998:        }
                    999:        csock = gNgStatSock;
                   1000:     }
                   1001: 
                   1002:     if (NgSendMsg(csock, path,
1.1.1.4 ! misho    1003:       NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0) {
        !          1004:        Perror("NgSendMsg to %s", path);
1.1       misho    1005:        return (0);
1.1.1.4 ! misho    1006:     }
        !          1007:     if (NgRecvMsg(csock, &u.reply, sizeof(u), NULL) < 0) {
        !          1008:        Perror("NgRecvMsg from %s", path);
        !          1009:        return (0);
        !          1010:     }
        !          1011: 
1.1       misho    1012:     return (ni->id);
                   1013: }
                   1014: 

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