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

1.1       misho       1: 
                      2: /*
                      3:  * iface.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 code copyright (c) 2000 Ruslan Ermilov
                     10:  * TCP MSSFIX contributed by Sergey Korolew <dsATbittu.org.ru>
                     11:  *
                     12:  */
                     13: 
                     14: #include "ppp.h"
                     15: #include "iface.h"
                     16: #include "ipcp.h"
                     17: #include "auth.h"
                     18: #include "ngfunc.h"
                     19: #include "netgraph.h"
                     20: #include "util.h"
                     21: 
                     22: #include <sys/sockio.h>
                     23: #include <sys/sysctl.h>
                     24: #include <net/if.h>
                     25: #include <net/if_types.h>
                     26: #include <net/if_dl.h>
                     27: #include <net/if_var.h>
                     28: #include <net/route.h>
                     29: #include <netinet/in_systm.h>
                     30: #include <netinet/in.h>
                     31: #include <netinet/in_var.h>
                     32: #include <netinet/if_ether.h>
                     33: #include <netinet6/nd6.h>
                     34: #include <netgraph/ng_message.h>
                     35: #include <netgraph/ng_iface.h>
                     36: #ifdef USE_NG_BPF
                     37: #include <netgraph/ng_bpf.h>
                     38: #endif
                     39: #include <netgraph/ng_tee.h>
                     40: #include <netgraph/ng_ksocket.h>
                     41: #include <netinet/ip_icmp.h>
                     42: #include <netinet/tcp.h>
                     43: #include <netinet/udp.h>
                     44: #ifdef USE_NG_TCPMSS
                     45: #include <netgraph/ng_tcpmss.h>
                     46: #endif
                     47: #ifdef USE_NG_IPACCT
                     48: #include <netgraph/ng_ipacct.h>
                     49: #undef r_ip_p  /* XXX:DIRTY CONFLICT! */
                     50: #endif
                     51: #ifdef USE_NG_NETFLOW
                     52: #include <netgraph/netflow/ng_netflow.h>
                     53: #endif
                     54: #ifdef USE_NG_CAR
                     55: #include <netgraph/ng_car.h>
                     56: #endif
                     57: 
                     58: #ifdef USE_NG_BPF
                     59: #include <pcap.h>
                     60: #endif
                     61: 
                     62: /*
                     63:  * DEFINITIONS
                     64:  */
                     65: 
                     66: /* Set menu options */
                     67: 
                     68:   enum {
                     69:     SET_IDLE,
                     70:     SET_SESSION,
                     71:     SET_ADDRS,
                     72:     SET_ROUTE,
                     73:     SET_MTU,
                     74:     SET_NAME,
                     75: #ifdef SIOCSIFDESCR
                     76:     SET_DESCR,
                     77: #endif
                     78: #ifdef SIOCAIFGROUP
                     79:     SET_GROUP,
                     80: #endif
                     81:     SET_UP_SCRIPT,
                     82:     SET_DOWN_SCRIPT,
                     83:     SET_ENABLE,
                     84:     SET_DISABLE
                     85:   };
                     86: 
                     87: /*
                     88:  * INTERNAL FUNCTIONS
                     89:  */
                     90: 
                     91:   static int   IfaceNgIpInit(Bund b, int ready);
                     92:   static void  IfaceNgIpShutdown(Bund b);
                     93:   static int   IfaceNgIpv6Init(Bund b, int ready);
                     94:   static void  IfaceNgIpv6Shutdown(Bund b);
                     95: 
                     96: #ifdef USE_NG_NETFLOW
                     97:   static int   IfaceInitNetflow(Bund b, char *path, char *hook, char in, char out);
                     98:   static int   IfaceSetupNetflow(Bund b, char in, char out);
                     99:   static void  IfaceShutdownNetflow(Bund b, char in, char out);
                    100: #endif
                    101: 
                    102: #ifdef USE_NG_IPACCT
                    103:   static int   IfaceInitIpacct(Bund b, char *path, char *hook);
                    104:   static void  IfaceShutdownIpacct(Bund b);
                    105: #endif
                    106: 
                    107: #ifdef USE_NG_NAT
                    108:   static int   IfaceInitNAT(Bund b, char *path, char *hook);
                    109:   static int   IfaceSetupNAT(Bund b);
                    110:   static void  IfaceShutdownNAT(Bund b);
                    111: #endif
                    112: 
                    113:   static int   IfaceInitTee(Bund b, char *path, char *hook, int v6);
                    114:   static void  IfaceShutdownTee(Bund b, int v6);
                    115: 
                    116: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
                    117:   static int    IfaceInitMSS(Bund b, char *path, char *hook);
                    118:   static void  IfaceSetupMSS(Bund b, uint16_t maxMSS);
                    119:   static void  IfaceShutdownMSS(Bund b);
                    120: #endif
                    121: 
                    122: #ifdef USE_NG_BPF
                    123:   static int    IfaceInitLimits(Bund b, char *path, char *hook);
                    124:   static void  IfaceSetupLimits(Bund b);
                    125:   static void  IfaceShutdownLimits(Bund b);
                    126: #endif
                    127: 
                    128:   static int   IfaceSetCommand(Context ctx, int ac, char *av[], void *arg);
                    129:   static void  IfaceSessionTimeout(void *arg);
                    130:   static void  IfaceIdleTimeout(void *arg);
                    131: 
                    132:   static void  IfaceCacheSend(Bund b);
                    133:   static void  IfaceCachePkt(Bund b, int proto, Mbuf pkt);
                    134:   static int   IfaceIsDemand(int proto, Mbuf pkt);
                    135: 
                    136: #ifdef USE_IPFW
                    137:   static int   IfaceAllocACL (struct acl_pool ***ap, int start, char * ifname, int number);
                    138:   static int   IfaceFindACL (struct acl_pool *ap, char * ifname, int number);
                    139:   static char *        IFaceParseACL (char * src, char * ifname);
                    140: #endif
                    141: 
                    142:   static int   IfaceSetName(Bund b, const char * ifname);
                    143: #ifdef SIOCSIFDESCR
                    144:   static int   IfaceSetDescr(Bund b, const char * ifdescr);
                    145: #endif
                    146: #ifdef SIOCAIFGROUP
                    147:   static int   IfaceAddGroup(Bund b, const char * ifgroup);
                    148:   static int   IfaceDelGroup(Bund b, const char * ifgroup);
                    149: #endif
                    150: /*
                    151:  * GLOBAL VARIABLES
                    152:  */
                    153: 
                    154:   const struct cmdtab IfaceSetCmds[] = {
                    155:     { "addrs {self} {peer}",           "Set interface addresses",
                    156:        IfaceSetCommand, NULL, 2, (void *) SET_ADDRS },
                    157:     { "route {dest}[/{width}]",                "Add IP route",
                    158:        IfaceSetCommand, NULL, 2, (void *) SET_ROUTE },
                    159:     { "mtu {size}",                    "Set max allowed interface MTU",
                    160:        IfaceSetCommand, NULL, 2, (void *) SET_MTU },
                    161:     { "name [{name}]",                 "Set interface name",
                    162:        IfaceSetCommand, NULL, 2, (void *) SET_NAME },
                    163: #ifdef SIOCSIFDESCR
                    164:     { "description [{descr}]",         "Set interface description",
                    165:        IfaceSetCommand, NULL, 2, (void *) SET_DESCR },
                    166: #endif
                    167: #ifdef SIOCAIFGROUP
                    168:     { "group [{group}]",               "Set interface group",
                    169:        IfaceSetCommand, NULL, 2, (void *) SET_GROUP },
                    170: #endif
                    171:     { "up-script [{progname}]",                "Interface up script",
                    172:        IfaceSetCommand, NULL, 2, (void *) SET_UP_SCRIPT },
                    173:     { "down-script [{progname}]",      "Interface down script",
                    174:        IfaceSetCommand, NULL, 2, (void *) SET_DOWN_SCRIPT },
                    175: #ifdef USE_NG_BPF
                    176:     { "idle {seconds}",                        "Idle timeout",
                    177:        IfaceSetCommand, NULL, 2, (void *) SET_IDLE },
                    178: #endif
                    179:     { "session {seconds}",             "Session timeout",
                    180:        IfaceSetCommand, NULL, 2, (void *) SET_SESSION },
                    181:     { "enable [opt ...]",              "Enable option",
                    182:        IfaceSetCommand, NULL, 2, (void *) SET_ENABLE },
                    183:     { "disable [opt ...]",             "Disable option",
                    184:        IfaceSetCommand, NULL, 2, (void *) SET_DISABLE },
                    185:     { NULL },
                    186:   };
                    187: 
                    188: /*
                    189:  * INTERNAL VARIABLES
                    190:  */
                    191: 
                    192:   static const struct confinfo gConfList[] = {
                    193:     { 0,       IFACE_CONF_ONDEMAND,            "on-demand"     },
                    194:     { 0,       IFACE_CONF_PROXY,               "proxy-arp"     },
                    195: #ifdef USE_NG_TCPMSS
                    196:     { 0,       IFACE_CONF_TCPMSSFIX,           "tcpmssfix"     },
                    197: #endif
                    198:     { 0,       IFACE_CONF_TEE,                 "tee"           },
                    199: #ifdef USE_NG_NAT
                    200:     { 0,       IFACE_CONF_NAT,                 "nat"           },
                    201: #endif
                    202: #ifdef USE_NG_NETFLOW
                    203:     { 0,       IFACE_CONF_NETFLOW_IN,          "netflow-in"    },
                    204:     { 0,       IFACE_CONF_NETFLOW_OUT,         "netflow-out"   },
                    205: #ifdef NG_NETFLOW_CONF_ONCE
                    206:     { 0,       IFACE_CONF_NETFLOW_ONCE,        "netflow-once"  },
                    207: #endif
                    208: #endif
                    209: #ifdef USE_NG_IPACCT
                    210:     { 0,       IFACE_CONF_IPACCT,              "ipacct"        },
                    211: #endif
                    212:     { 0,       0,                              NULL            },
                    213:   };
                    214: 
                    215: #ifdef USE_IPFW
                    216:   struct acl_pool * rule_pool = NULL; /* Pointer to the first element in the list of rules */
                    217:   struct acl_pool * pipe_pool = NULL; /* Pointer to the first element in the list of pipes */
                    218:   struct acl_pool * queue_pool = NULL; /* Pointer to the first element in the list of queues */
                    219:   struct acl_pool * table_pool = NULL; /* Pointer to the first element in the list of tables */
                    220:   int rule_pool_start = 10000; /* Initial number of ipfw rules pool */
                    221:   int pipe_pool_start = 10000; /* Initial number of ipfw dummynet pipe pool */
                    222:   int queue_pool_start = 10000; /* Initial number of ipfw dummynet queue pool */
                    223:   int table_pool_start = 32; /* Initial number of ipfw tables pool */
                    224: #endif
                    225: 
                    226: #ifdef USE_NG_BPF
                    227:   /* A BPF filter that matches TCP SYN packets */
                    228:   static const struct bpf_insn gTCPSYNProg[] = {
                    229: /*00*/ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 9),              /* A <- IP protocol */
                    230: /*01*/ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, 6), /* !TCP => 8 */
                    231: /*02*/ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 6),      /* A <- fragmentation offset */
                    232: /*03*/ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 4, 0), /* fragment => 8 */
                    233: /*04*/ BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 0),             /* X <- header len */
                    234: /*05*/ BPF_STMT(BPF_LD+BPF_B+BPF_IND, 13),             /* A <- TCP flags */
                    235: /*06*/ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, TH_SYN, 0, 1), /* !TH_SYN => 8 */
                    236: /*07*/ BPF_STMT(BPF_RET+BPF_K, (u_int)-1),             /* accept packet */
                    237: /*08*/ BPF_STMT(BPF_RET+BPF_K, 0),                     /* reject packet */
                    238:   };
                    239: 
                    240:   #define TCPSYN_PROG_LEN      (sizeof(gTCPSYNProg) / sizeof(*gTCPSYNProg))
                    241: 
                    242:   /* A BPF filter that matches nothing */
                    243:   static const struct bpf_insn gNoMatchProg[] = {
                    244:        BPF_STMT(BPF_RET+BPF_K, 0)
                    245:   };
                    246: 
                    247:   #define NOMATCH_PROG_LEN     (sizeof(gNoMatchProg) / sizeof(*gNoMatchProg))
                    248: 
                    249:   /* A BPF filter that matches everything */
                    250:   static const struct bpf_insn gMatchProg[] = {
                    251:        BPF_STMT(BPF_RET+BPF_K, (u_int)-1)
                    252:   };
                    253: 
                    254:   #define MATCH_PROG_LEN       (sizeof(gMatchProg) / sizeof(*gMatchProg))
                    255: #endif /* USE_NG_BPF */
                    256: 
                    257: #define IN6MASK128     {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
                    258:                            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}
                    259: static const struct in6_addr in6mask128 = IN6MASK128;
                    260: 
                    261: 
                    262: /*
                    263:  * IfaceInit()
                    264:  */
                    265: 
                    266: void
                    267: IfaceInit(Bund b)
                    268: {
                    269:   IfaceState   const iface = &b->iface;
                    270: 
                    271:   /* Default configuration */
                    272:   iface->mtu = NG_IFACE_MTU_DEFAULT;
                    273:   iface->max_mtu = NG_IFACE_MTU_DEFAULT;
                    274: #ifdef SIOCSIFDESCR
                    275:   iface->ifdescr = NULL;
                    276:   iface->conf.ifdescr = NULL;
                    277: #endif
                    278:   Disable(&iface->options, IFACE_CONF_ONDEMAND);
                    279:   Disable(&iface->options, IFACE_CONF_PROXY);
                    280:   Disable(&iface->options, IFACE_CONF_TCPMSSFIX);
                    281: #ifdef USE_NG_NAT
                    282:   NatInit(b);
                    283: #endif
                    284: #ifdef USE_NG_BPF
                    285:   SLIST_INIT(&iface->ss[0]);
                    286:   SLIST_INIT(&iface->ss[1]);
                    287: #endif
                    288: }
                    289: 
                    290: /*
                    291:  * IfaceInst()
                    292:  */
                    293: 
                    294: void
                    295: IfaceInst(Bund b, Bund bt)
                    296: {
                    297:     IfaceState const iface = &b->iface;
                    298: 
                    299:     memcpy(iface, &bt->iface, sizeof(*iface));
                    300: 
                    301:     /* Copy interface name from template config to current */
                    302:     if (bt->iface.conf.ifname[0] != 0 && b->tmpl == 0) {
                    303:         snprintf(iface->conf.ifname, sizeof(iface->conf.ifname), "%s%d",
                    304:              bt->iface.conf.ifname, b->id);
                    305:         Log(LG_IFACE2, ("[%s] IFACE: Set conf.ifname to ", iface->conf.ifname));
                    306:     }
                    307: }
                    308: 
                    309: /*
                    310:  * IfaceDestroy()
                    311:  */
                    312: 
                    313: void
                    314: IfaceDestroy(Bund b)
                    315: {
                    316: #ifdef SIOCSIFDESCR
                    317:     IfaceState const iface = &b->iface;
                    318: 
                    319:     if (iface->conf.ifdescr != NULL)
                    320:        Freee(iface->conf.ifdescr);
                    321: #endif
                    322: }
                    323: 
                    324: /*
                    325:  * IfaceOpen()
                    326:  *
                    327:  * Open the interface layer
                    328:  */
                    329: 
                    330: void
                    331: IfaceOpen(Bund b)
                    332: {
                    333:     IfaceState const iface = &b->iface;
                    334: 
                    335:     Log(LG_IFACE, ("[%s] IFACE: Open event", b->name));
                    336: 
                    337:     /* Open is useless without on-demand. */
                    338:     if (!Enabled(&iface->options, IFACE_CONF_ONDEMAND)) {
                    339:        Log(LG_ERR, ("[%s] 'open iface' is useless without on-demand enabled", b->name));
                    340:        return;
                    341:     }
                    342: 
                    343:     /* If interface is already open do nothing */
                    344:     if (iface->open)
                    345:        return;
                    346:     iface->open = TRUE;
                    347: 
                    348:     /* If on-demand, bring up system interface immediately and start
                    349:      listening for outgoing packets. The next outgoing packet will
                    350:      cause us to open the lower layer(s) */
                    351:     BundNcpsJoin(b, NCP_NONE);
                    352: }
                    353: 
                    354: /*
                    355:  * IfaceClose()
                    356:  *
                    357:  * Close the interface layer
                    358:  */
                    359: 
                    360: void
                    361: IfaceClose(Bund b)
                    362: {
                    363:     IfaceState const iface = &b->iface;
                    364: 
                    365:     Log(LG_IFACE, ("[%s] IFACE: Close event", b->name));
                    366: 
                    367:     /* If interface is already closed do nothing */
                    368:     if (!iface->open)
                    369:        return;
                    370:     iface->open = FALSE;
                    371: 
                    372:     /* If there was on-demand, tell that it is not needed anymore */
                    373:     BundNcpsLeave(b, NCP_NONE);
                    374: }
                    375: 
                    376: /*
                    377:  * IfaceOpenCmd()
                    378:  *
                    379:  * Open the interface layer
                    380:  */
                    381: 
                    382: int
                    383: IfaceOpenCmd(Context ctx)
                    384: {
                    385:     if (ctx->bund->tmpl)
                    386:        Error("impossible to open template");
                    387:     IfaceOpen(ctx->bund);
                    388:     return (0);
                    389: }
                    390: 
                    391: /*
                    392:  * IfaceCloseCmd()
                    393:  *
                    394:  * Close the interface layer
                    395:  */
                    396: 
                    397: int
                    398: IfaceCloseCmd(Context ctx)
                    399: {
                    400:     if (ctx->bund->tmpl)
                    401:        Error("impossible to close template");
                    402:     IfaceClose(ctx->bund);
                    403:     return (0);
                    404: }
                    405: 
                    406: /*
                    407:  * IfaceUp()
                    408:  *
                    409:  * Our underlying PPP bundle is ready for traffic.
                    410:  * We may signal that the interface is in DoD with the IFF_LINK0 flag.
                    411:  */
                    412: 
                    413: void
                    414: IfaceUp(Bund b, int ready)
                    415: {
                    416:   IfaceState   const iface = &b->iface;
                    417:   int          session_timeout = 0, idle_timeout = 0;
                    418: #ifdef USE_IPFW
                    419:   struct acl   *acls, *acl;
                    420:   char                 *buf;
                    421:   struct acl_pool      **poollast;
                    422:   int                  poollaststart;
                    423:   int          prev_number;
                    424:   int          prev_real_number;
                    425: #endif
                    426: 
                    427:   Log(LG_IFACE, ("[%s] IFACE: Up event", b->name));
                    428:   iface->last_up = time(NULL);
                    429: 
                    430:   if (ready) {
                    431: 
                    432:     /* Start Session timer */
                    433:     if (b->params.session_timeout > 0) {
                    434:        session_timeout = b->params.session_timeout;
                    435:     } else if (iface->session_timeout > 0) {
                    436:        session_timeout = iface->session_timeout;
                    437:     }
                    438: 
                    439:     if (session_timeout > 0) {
                    440:        Log(LG_IFACE2, ("[%s] IFACE: session-timeout: %d seconds", 
                    441:            b->name, session_timeout));
                    442:        if (session_timeout > INT_MAX / 1100) {
                    443:            session_timeout = INT_MAX / 1100;
                    444:            Log(LG_ERR, ("[%s] IFACE: session-timeout limited to %d seconds", 
                    445:                b->name, session_timeout));
                    446:        }
                    447:        TimerInit(&iface->sessionTimer, "IfaceSession",
                    448:            session_timeout * SECONDS, IfaceSessionTimeout, b);
                    449:        TimerStart(&iface->sessionTimer);
                    450:     }
                    451: 
                    452:     /* Start idle timer */
                    453:     if (b->params.idle_timeout > 0) {
                    454:        idle_timeout = b->params.idle_timeout;
                    455:     } else if (iface->idle_timeout > 0) {
                    456:        idle_timeout = iface->idle_timeout;
                    457:     }
                    458:     
                    459:     if (idle_timeout > 0) {
                    460:        Log(LG_IFACE2, ("[%s] IFACE: idle-timeout: %d seconds", 
                    461:            b->name, idle_timeout));
                    462:        if (idle_timeout > INT_MAX / 1100 * IFACE_IDLE_SPLIT) {
                    463:            idle_timeout = INT_MAX / 1100 * IFACE_IDLE_SPLIT;
                    464:            Log(LG_ERR, ("[%s] IFACE: idle-timeout limited to %d seconds", 
                    465:                b->name, idle_timeout));
                    466:        }
                    467:        TimerInit(&iface->idleTimer, "IfaceIdle",
                    468:            idle_timeout * SECONDS / IFACE_IDLE_SPLIT, IfaceIdleTimeout, b);
                    469:        TimerStart(&iface->idleTimer);
                    470:        iface->traffic[1] = TRUE;
                    471:        iface->traffic[0] = FALSE;
                    472: 
                    473:        /* Reset statistics */
                    474:        memset(&iface->idleStats, 0, sizeof(iface->idleStats));
                    475:     }
                    476: 
                    477:     /* Update interface name and description */
                    478:     if (b->params.ifname[0] != 0) {
                    479:        if (IfaceSetName(b, b->params.ifname) != -1)
                    480:            Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Rename interface %s to %s",
                    481:                b->name, iface->ngname, b->params.ifname));
                    482:     } else if (iface->conf.ifname[0] != 0) {
                    483:        if (IfaceSetName(b, iface->conf.ifname) != -1)
                    484:            Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Rename interface %s to %s",
                    485:                b->name, iface->ngname, iface->conf.ifname));
                    486:     }
                    487: #ifdef SIOCSIFDESCR
                    488:     if (b->params.ifdescr != NULL) {
                    489:        if (IfaceSetDescr(b, b->params.ifdescr) != -1) {
                    490:            Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add description \"%s\"",
                    491:                b->name, b->params.ifdescr));
                    492:            iface->ifdescr = b->params.ifdescr;
                    493:        }
                    494:     }
                    495: #endif
                    496: #ifdef SIOCAIFGROUP
                    497:     if (iface->conf.ifgroup[0] != 0) {
                    498:        if (IfaceAddGroup(b, iface->conf.ifgroup) != -1)
                    499:            Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add group %s to %s",
                    500:                b->name, iface->conf.ifgroup, iface->ngname));
                    501:     }
                    502:     if (b->params.ifgroup[0] != 0) {
                    503:        if (IfaceAddGroup(b, b->params.ifgroup) != -1)
                    504:            Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add group %s to %s",
                    505:                b->name, b->params.ifgroup, iface->ngname));
                    506:     }
                    507: #endif
                    508: #ifdef USE_IPFW
                    509:   /* Allocate ACLs */
                    510:   acls = b->params.acl_pipe;
                    511:   poollast = &pipe_pool;
                    512:   poollaststart = pipe_pool_start;
                    513:   while (acls != NULL) {
                    514:     acls->real_number = IfaceAllocACL(&poollast, poollaststart, iface->ifname, acls->number);
                    515:     poollaststart = acls->real_number;
                    516:     acls = acls->next;
                    517:   };
                    518:   acls = b->params.acl_queue;
                    519:   poollast = &queue_pool;
                    520:   poollaststart = queue_pool_start;
                    521:   while (acls != NULL) {
                    522:     acls->real_number = IfaceAllocACL(&poollast, poollaststart, iface->ifname, acls->number);
                    523:     poollaststart = acls->real_number;
                    524:     acls = acls->next;
                    525:   };
                    526:   prev_number = -1;
                    527:   prev_real_number = -1;
                    528:   acls = b->params.acl_table;
                    529:   poollast = &table_pool;
                    530:   poollaststart = table_pool_start;
                    531:   while (acls != NULL) {
                    532:     if (acls->real_number == 0) {
                    533:        if (acls->number == prev_number) { /* ACL list is presorted so we need not allocate if equal */
                    534:            acls->real_number = prev_real_number;
                    535:        } else {
                    536:            acls->real_number = IfaceAllocACL(&poollast, poollaststart, iface->ifname, acls->number);
                    537:            poollaststart = acls->real_number;
                    538:            prev_number = acls->number;
                    539:            prev_real_number = acls->real_number;
                    540:        }
                    541:     }
                    542:     acls = acls->next;
                    543:   };
                    544:   acls = b->params.acl_rule;
                    545:   poollast = &rule_pool;
                    546:   poollaststart = rule_pool_start;
                    547:   while (acls != NULL) {
                    548:     acls->real_number = IfaceAllocACL(&poollast, poollaststart, iface->ifname, acls->number);
                    549:     poollaststart = acls->real_number;
                    550:     acls = acls->next;
                    551:   };
                    552: 
                    553:   /* Set ACLs */
                    554:   acls = b->params.acl_pipe;
                    555:   while (acls != NULL) {
                    556:     ExecCmd(LG_IFACE2, b->name, "%s pipe %d config %s", PATH_IPFW, acls->real_number, acls->rule);
                    557:     acls = acls->next;
                    558:   }
                    559:   acls = b->params.acl_queue;
                    560:   while (acls != NULL) {
                    561:     buf = IFaceParseACL(acls->rule,iface->ifname);
                    562:     ExecCmd(LG_IFACE2, b->name, "%s queue %d config %s", PATH_IPFW, acls->real_number, buf);
                    563:     Freee(buf);
                    564:     acls = acls->next;
                    565:   }
                    566:   acls = b->params.acl_table;
                    567:   while (acls != NULL) {
                    568:     acl = Mdup(MB_IFACE, acls, sizeof(struct acl) + strlen(acls->rule));
                    569:     acl->next = iface->tables;
                    570:     iface->tables = acl;
                    571:     ExecCmd(LG_IFACE2, b->name, "%s table %d add %s", PATH_IPFW, acls->real_number, acls->rule);
                    572:     acls = acls->next;
                    573:   };
                    574:   acls = b->params.acl_rule;
                    575:   while (acls != NULL) {
                    576:     buf = IFaceParseACL(acls->rule, iface->ifname);
                    577:     ExecCmd(LG_IFACE2, b->name, "%s add %d %s via %s", PATH_IPFW, acls->real_number, buf, iface->ifname);
                    578:     Freee(buf);
                    579:     acls = acls->next;
                    580:   };
                    581: #endif /* USE_IPFW */
                    582: 
                    583:   };
                    584: 
                    585:   /* Bring up system interface */
                    586:   IfaceChangeFlags(b, 0, IFF_UP | (ready?0:IFF_LINK0));
                    587: 
                    588:   /* Send any cached packets */
                    589:   IfaceCacheSend(b);
                    590: 
                    591: }
                    592: 
                    593: /*
                    594:  * IfaceDown()
                    595:  *
                    596:  * Our packet transport mechanism is no longer ready for traffic.
                    597:  */
                    598: 
                    599: void
                    600: IfaceDown(Bund b)
                    601: {
                    602:   IfaceState   const iface = &b->iface;
                    603: #ifdef USE_IPFW
                    604:   struct acl_pool      **rp, *rp1;
                    605:   char         cb[32768];
                    606:   struct acl    *acl, *aclnext;
                    607: #endif
                    608: 
                    609:   Log(LG_IFACE, ("[%s] IFACE: Down event", b->name));
                    610: 
                    611:   /* Bring down system interface */
                    612:   IfaceChangeFlags(b, IFF_UP | IFF_LINK0, 0);
                    613: 
                    614:   TimerStop(&iface->idleTimer);
                    615:   TimerStop(&iface->sessionTimer);
                    616: 
                    617: #ifdef USE_IPFW
                    618:   /* Remove rule ACLs */
                    619:   rp = &rule_pool;
                    620:   cb[0]=0;
                    621:   while (*rp != NULL) {
                    622:     if (strncmp((*rp)->ifname, iface->ifname, IFNAMSIZ) == 0) {
                    623:       sprintf(cb+strlen(cb), " %d", (*rp)->real_number);
                    624:       rp1 = *rp;
                    625:       *rp = (*rp)->next;
                    626:       Freee(rp1);
                    627:     } else {
                    628:       rp = &((*rp)->next);
                    629:     };
                    630:   };
                    631:   if (cb[0]!=0)
                    632:     ExecCmdNosh(LG_IFACE2, b->name, "%s delete%s",
                    633:       PATH_IPFW, cb);
                    634: 
                    635:   /* Remove table ACLs */
                    636:   rp = &table_pool;
                    637:   while (*rp != NULL) {
                    638:     if (strncmp((*rp)->ifname, iface->ifname, IFNAMSIZ) == 0) {
                    639:       rp1 = *rp;
                    640:       *rp = (*rp)->next;
                    641:       Freee(rp1);
                    642:     } else {
                    643:       rp = &((*rp)->next);
                    644:     };
                    645:   };
                    646:   acl = iface->tables;
                    647:   while (acl != NULL) {
                    648:     ExecCmd(LG_IFACE2, b->name, "%s table %d delete %s",
                    649:        PATH_IPFW, acl->real_number, acl->rule);
                    650:     aclnext = acl->next;
                    651:     Freee(acl);
                    652:     acl = aclnext;
                    653:   };
                    654:   iface->tables = NULL;
                    655: 
                    656:   /* Remove queue ACLs */
                    657:   rp = &queue_pool;
                    658:   cb[0]=0;
                    659:   while (*rp != NULL) {
                    660:     if (strncmp((*rp)->ifname, iface->ifname, IFNAMSIZ) == 0) {
                    661:       sprintf(cb+strlen(cb), " %d", (*rp)->real_number);
                    662:       rp1 = *rp;
                    663:       *rp = (*rp)->next;
                    664:       Freee(rp1);
                    665:     } else {
                    666:       rp = &((*rp)->next);
                    667:     };
                    668:   };
                    669:   if (cb[0]!=0)
                    670:     ExecCmdNosh(LG_IFACE2, b->name, "%s queue delete%s",
                    671:       PATH_IPFW, cb);
                    672: 
                    673:   /* Remove pipe ACLs */
                    674:   rp = &pipe_pool;
                    675:   cb[0]=0;
                    676:   while (*rp != NULL) {
                    677:     if (strncmp((*rp)->ifname, iface->ifname, IFNAMSIZ) == 0) {
                    678:       sprintf(cb+strlen(cb), " %d", (*rp)->real_number);
                    679:       rp1 = *rp;
                    680:       *rp = (*rp)->next;
                    681:       Freee(rp1);
                    682:     } else {
                    683:       rp = &((*rp)->next);
                    684:     };
                    685:   };
                    686:   if (cb[0]!=0)
                    687:     ExecCmdNosh(LG_IFACE2, b->name, "%s pipe delete%s",
                    688:       PATH_IPFW, cb);
                    689: #endif /* USE_IPFW */
                    690: 
                    691:     /* Revert interface name and description */
                    692: 
                    693:     if (strcmp(iface->ngname, iface->ifname) != 0) {
                    694:        if (iface->conf.ifname[0] != 0) {
                    695:            /* Restore to config defined */
                    696:            if (IfaceSetName(b, iface->conf.ifname) != -1)
                    697:                Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Rename interface %s to %s",
                    698:                    b->name, iface->ifname, iface->conf.ifname));
                    699:        } else {
                    700:            /* Restore to original interface name */
                    701:            if (IfaceSetName(b, iface->ngname) != -1)
                    702:                Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Rename interface %s to %s",
                    703:                    b->name, iface->ifname, iface->ngname));
                    704:        }
                    705:     }
                    706: #ifdef SIOCSIFDESCR
                    707:     if (iface->ifdescr != NULL) {
                    708:        if (iface->conf.ifdescr != NULL) {
                    709:            /* Restore to config defined */
                    710:            if (IfaceSetDescr(b, iface->conf.ifdescr) != -1) {
                    711:                Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Set description \"%s\"",
                    712:                    b->name, iface->conf.ifdescr));
                    713:                iface->ifdescr = iface->conf.ifdescr;
                    714:            } else
                    715:                iface->ifdescr = NULL;
                    716:        } else {
                    717:            /* Restore to original (empty) */
                    718:            if (IfaceSetDescr(b, "") != -1) {
                    719:                Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Clear description",
                    720:                    b->name));
                    721:            }
                    722:            iface->ifdescr = NULL;
                    723:        }
                    724:     }
                    725: #endif
                    726: #ifdef SIOCAIFGROUP
                    727:     if (b->params.ifgroup[0] != 0) {
                    728:        if (IfaceDelGroup(b, b->params.ifgroup) != -1)
                    729:            Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Remove group %s from %s",
                    730:                b->name, b->params.ifgroup, iface->ngname));
                    731:     }
                    732: #endif
                    733: }
                    734: 
                    735: /*
                    736:  * IfaceListenInput()
                    737:  *
                    738:  * A packet was received on our demand snooping hook. Stimulate a connection.
                    739:  */
                    740: 
                    741: void
                    742: IfaceListenInput(Bund b, int proto, Mbuf pkt)
                    743: {
                    744:     IfaceState const iface = &b->iface;
                    745:     int                const isDemand = IfaceIsDemand(proto, pkt);
                    746: 
                    747:     /* Does this count as demand traffic? */
                    748:     if (iface->open && isDemand) {
                    749:        iface->traffic[0] = TRUE;
                    750:         Log(LG_IFACE, ("[%s] IFACE: Outgoing %s packet demands connection", b->name,
                    751:            (proto==PROTO_IP)?"IP":"IPv6"));
                    752:        RecordLinkUpDownReason(b, NULL, 1, STR_DEMAND, NULL);
                    753:         BundOpen(b);
                    754:         IfaceCachePkt(b, proto, pkt);
                    755:     } else {
                    756:        mbfree(pkt);
                    757:     }
                    758: }
                    759: 
                    760: #ifdef USE_IPFW
                    761: /*
                    762:  * IfaceAllocACL ()
                    763:  *
                    764:  * Allocates unique real number for new ACL and adds it to the list of used ones.
                    765:  */
                    766: 
                    767: static int
                    768: IfaceAllocACL(struct acl_pool ***ap, int start, char *ifname, int number)
                    769: {
                    770:     int        i;
                    771:     struct acl_pool **rp,*rp1;
                    772: 
                    773:     rp1 = Malloc(MB_IFACE, sizeof(struct acl_pool));
                    774:     strlcpy(rp1->ifname, ifname, sizeof(rp1->ifname));
                    775:     rp1->acl_number = number;
                    776: 
                    777:     rp = *ap;
                    778:     i = start;
                    779:     while (*rp != NULL && (*rp)->real_number <= i) {
                    780:         i = (*rp)->real_number+1;
                    781:         rp = &((*rp)->next);
                    782:     };
                    783:     if (*rp == NULL) {
                    784:         rp1->next = NULL;
                    785:     } else {
                    786:         rp1->next = *rp;
                    787:     };
                    788:     rp1->real_number = i;
                    789:     *rp = rp1;
                    790:     *ap = rp;
                    791:     return(i);
                    792: }
                    793: 
                    794: /*
                    795:  * IfaceFindACL ()
                    796:  *
                    797:  * Finds ACL in the list and gets its real number.
                    798:  */
                    799: 
                    800: static int
                    801: IfaceFindACL (struct acl_pool *ap, char * ifname, int number)
                    802: {
                    803:     int        i;
                    804:     struct acl_pool *rp;
                    805: 
                    806:     rp=ap;
                    807:     i=-1;
                    808:     while (rp != NULL) {
                    809:        if ((rp->acl_number == number) && (strncmp(rp->ifname,ifname,IFNAMSIZ) == 0)) {
                    810:            i = rp->real_number;
                    811:            break;
                    812:        };
                    813:         rp = rp->next;
                    814:     };
                    815:     return(i);
                    816: }
                    817: 
                    818: /*
                    819:  * IFaceParseACL ()
                    820:  *
                    821:  * Parces ACL and replaces %r, %p and %q macroses 
                    822:  * by the real numbers of rules, queues and pipes.
                    823:  */
                    824: 
                    825: static char *
                    826: IFaceParseACL (char * src, char * ifname)
                    827: {
                    828:     char *buf,*buf1;
                    829:     char *begin,*param,*end;
                    830:     char t;
                    831:     int num,real_number;
                    832:     struct acl_pool *ap;
                    833:     
                    834:     buf = Malloc(MB_IFACE, ACL_LEN);
                    835:     buf1 = Malloc(MB_IFACE, ACL_LEN);
                    836: 
                    837:     strlcpy(buf, src, ACL_LEN);
                    838:     do {
                    839:         end = buf;
                    840:        begin = strsep(&end, "%");
                    841:        param = strsep(&end, " ");
                    842:        if (param != NULL) {
                    843:            if (sscanf(param,"%c%d", &t, &num) == 2) {
                    844:                switch (t) {
                    845:                    case 'r':
                    846:                        ap = rule_pool;
                    847:                        break;
                    848:                    case 'p':
                    849:                        ap = pipe_pool;
                    850:                        break;
                    851:                    case 'q':
                    852:                        ap = queue_pool;
                    853:                        break;
                    854:                    case 't':
                    855:                        ap = table_pool;
                    856:                        break;
                    857:                    default:
                    858:                        ap = NULL;
                    859:                };
                    860:                real_number = IfaceFindACL(ap,ifname,num);
                    861:                if (end != NULL) {
                    862:                    snprintf(buf1, ACL_LEN, "%s%d %s", begin, real_number, end);
                    863:                } else {
                    864:                    snprintf(buf1, ACL_LEN, "%s%d", begin, real_number);
                    865:                };
                    866:                strlcpy(buf, buf1, ACL_LEN);
                    867:            };
                    868:        };
                    869:     } while (end != NULL);
                    870:     Freee(buf1);
                    871:     return(buf);
                    872: }
                    873: #endif /* USE_IPFW */
                    874: 
                    875: /*
                    876:  * IfaceIpIfaceUp()
                    877:  *
                    878:  * Bring up the IP interface. The "ready" flag means that
                    879:  * IPCP is also up and we can deliver packets immediately.
                    880:  */
                    881: 
                    882: int
                    883: IfaceIpIfaceUp(Bund b, int ready)
                    884: {
                    885:     IfaceState         const iface = &b->iface;
                    886:     struct sockaddr_dl hwa;
                    887:     char               hisaddr[20];
                    888:     IfaceRoute         r;
                    889:     u_char             *ether;
                    890: 
                    891:     if (ready && !iface->conf.self_addr_force) {
                    892:        in_addrtou_range(&b->ipcp.want_addr, 32, &iface->self_addr);
                    893:     } else {
                    894:        u_rangecopy(&iface->conf.self_addr, &iface->self_addr);
                    895:     }
                    896:     if (ready && !iface->conf.peer_addr_force) {
                    897:        in_addrtou_addr(&b->ipcp.peer_addr, &iface->peer_addr);
                    898:     } else {
                    899:        u_addrcopy(&iface->conf.peer_addr, &iface->peer_addr);
                    900:     }
                    901: 
                    902:     if (IfaceNgIpInit(b, ready)) {
                    903:        Log(LG_ERR, ("[%s] IFACE: IfaceNgIpInit() error, closing IPCP", b->name));
                    904:        FsmFailure(&b->ipcp.fsm, FAIL_NEGOT_FAILURE);
                    905:        return (-1);
                    906:     };
                    907: 
                    908:     /* Set addresses */
                    909:     if (!u_rangeempty(&iface->self_addr) &&
                    910:            IfaceChangeAddr(b, 1, &iface->self_addr, &iface->peer_addr)) {
                    911:        Log(LG_ERR, ("[%s] IFACE: IfaceChangeAddr() error, closing IPCP", b->name));
                    912:        FsmFailure(&b->ipcp.fsm, FAIL_NEGOT_FAILURE);
                    913:        return (-1);
                    914:     };
                    915: 
                    916:     /* Proxy ARP for peer if desired and peer's address is known */
                    917:     u_addrclear(&iface->proxy_addr);
                    918:     if (Enabled(&iface->options, IFACE_CONF_PROXY)) {
                    919:        if (u_addrempty(&iface->peer_addr)) {
                    920:            Log(LG_IFACE,
                    921:                ("[%s] IFACE: Can't proxy arp for %s",
                    922:                b->name, u_addrtoa(&iface->peer_addr,hisaddr,sizeof(hisaddr))));
                    923:        } else if (GetEther(&iface->peer_addr, &hwa) < 0) {
                    924:            Log(LG_IFACE,
                    925:                ("[%s] IFACE: No interface to proxy arp on for %s",
                    926:                b->name, u_addrtoa(&iface->peer_addr,hisaddr,sizeof(hisaddr))));
                    927:        } else {
                    928:            ether = (u_char *) LLADDR(&hwa);
                    929:            if (ExecCmdNosh(LG_IFACE2, b->name, 
                    930:                "%s -S %s %x:%x:%x:%x:%x:%x pub",
                    931:                PATH_ARP, u_addrtoa(&iface->peer_addr,hisaddr,sizeof(hisaddr)),
                    932:                ether[0], ether[1], ether[2],
                    933:                ether[3], ether[4], ether[5]) == 0)
                    934:            iface->proxy_addr = iface->peer_addr;
                    935:        }
                    936:     }
                    937:   
                    938:     /* Add static routes */
                    939:     SLIST_FOREACH(r, &iface->routes, next) {
                    940:        if (u_rangefamily(&r->dest)==AF_INET) {
                    941:            r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_addr) == 0);
                    942:        }
                    943:     }
                    944:     /* Add dynamic routes */
                    945:     SLIST_FOREACH(r, &b->params.routes, next) {
                    946:        if (u_rangefamily(&r->dest)==AF_INET) {
                    947:            r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_addr) == 0);
                    948:        }
                    949:     }
                    950: 
                    951: #ifdef USE_NG_NAT
                    952:     /* Set NAT IP */
                    953:     if (iface->nat_up)
                    954:        IfaceSetupNAT(b);
                    955: #endif
                    956: 
                    957:     /* Call "up" script */
                    958:     if (*iface->up_script) {
                    959:        char    selfbuf[40],peerbuf[40];
                    960:        char    ns1buf[21], ns2buf[21];
                    961:        int     res;
                    962: 
                    963:        if(b->ipcp.want_dns[0].s_addr != 0)
                    964:            snprintf(ns1buf, sizeof(ns1buf), "dns1 %s", inet_ntoa(b->ipcp.want_dns[0]));
                    965:        else
                    966:            ns1buf[0] = '\0';
                    967:        if(b->ipcp.want_dns[1].s_addr != 0)
                    968:            snprintf(ns2buf, sizeof(ns2buf), "dns2 %s", inet_ntoa(b->ipcp.want_dns[1]));
                    969:        else
                    970:            ns2buf[0] = '\0';
                    971: 
                    972:        res = ExecCmd(LG_IFACE2, b->name, "%s %s inet %s %s '%s' '%s' '%s' '%s'",
                    973:            iface->up_script, iface->ifname, u_rangetoa(&iface->self_addr,selfbuf, sizeof(selfbuf)),
                    974:            u_addrtoa(&iface->peer_addr, peerbuf, sizeof(peerbuf)), 
                    975:            *b->params.authname ? b->params.authname : "-", 
                    976:            ns1buf, ns2buf, *b->params.peeraddr ? b->params.peeraddr : "-");
                    977:        if (res != 0) {
                    978:            FsmFailure(&b->ipcp.fsm, FAIL_NEGOT_FAILURE);
                    979:            return (-1);
                    980:        }
                    981:     }
                    982:     return (0);
                    983: }
                    984: 
                    985: /*
                    986:  * IfaceIpIfaceDown()
                    987:  *
                    988:  * Bring down the IP interface. This implies we're no longer ready.
                    989:  */
                    990: 
                    991: void
                    992: IfaceIpIfaceDown(Bund b)
                    993: {
                    994:     IfaceState const iface = &b->iface;
                    995:     IfaceRoute r;
                    996:     char       buf[48];
                    997: 
                    998:     /* Call "down" script */
                    999:     if (*iface->down_script) {
                   1000:        char    selfbuf[40],peerbuf[40];
                   1001: 
                   1002:        ExecCmd(LG_IFACE2, b->name, "%s %s inet %s %s '%s' '%s'",
                   1003:            iface->down_script, iface->ifname, u_rangetoa(&iface->self_addr,selfbuf, sizeof(selfbuf)),
                   1004:            u_addrtoa(&iface->peer_addr, peerbuf, sizeof(peerbuf)), 
                   1005:            *b->params.authname ? b->params.authname : "-",
                   1006:            *b->params.peeraddr ? b->params.peeraddr : "-");
                   1007:     }
                   1008: 
                   1009:     /* Delete dynamic routes */
                   1010:     SLIST_FOREACH(r, &b->params.routes, next) {
                   1011:        if (u_rangefamily(&r->dest)==AF_INET) {
                   1012:            if (!r->ok)
                   1013:                continue;
                   1014:            IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_addr);
                   1015:            r->ok = 0;
                   1016:        }
                   1017:     }
                   1018:     /* Delete static routes */
                   1019:     SLIST_FOREACH(r, &iface->routes, next) {
                   1020:        if (u_rangefamily(&r->dest)==AF_INET) {
                   1021:            if (!r->ok)
                   1022:                continue;
                   1023:            IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_addr);
                   1024:            r->ok = 0;
                   1025:        }
                   1026:     }
                   1027: 
                   1028:     /* Delete any proxy arp entry */
                   1029:     if (!u_addrempty(&iface->proxy_addr))
                   1030:        ExecCmdNosh(LG_IFACE2, b->name, "%s -d %s", PATH_ARP, u_addrtoa(&iface->proxy_addr, buf, sizeof(buf)));
                   1031:     u_addrclear(&iface->proxy_addr);
                   1032: 
                   1033:     /* Remove address from interface */
                   1034:     if (!u_rangeempty(&iface->self_addr))
                   1035:        IfaceChangeAddr(b, 0, &iface->self_addr, &iface->peer_addr);
                   1036:     
                   1037:     IfaceNgIpShutdown(b);
                   1038: }
                   1039: 
                   1040: /*
                   1041:  * IfaceIpv6IfaceUp()
                   1042:  *
                   1043:  * Bring up the IPv6 interface. The "ready" flag means that
                   1044:  * IPv6CP is also up and we can deliver packets immediately.
                   1045:  */
                   1046: 
                   1047: int
                   1048: IfaceIpv6IfaceUp(Bund b, int ready)
                   1049: {
                   1050:     IfaceState         const iface = &b->iface;
                   1051:     IfaceRoute         r;
                   1052: 
                   1053:     if (ready && !iface->conf.self_ipv6_addr_force) {
                   1054:         iface->self_ipv6_addr.family = AF_INET6;
                   1055:         iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[0] = 0x80fe;  /* Network byte order */
                   1056:         iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[1] = 0x0000;
                   1057:         iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[2] = 0x0000;
                   1058:         iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[3] = 0x0000;
                   1059:         iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[4] = ((u_short*)b->ipv6cp.myintid)[0];
                   1060:         iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[5] = ((u_short*)b->ipv6cp.myintid)[1];
                   1061:         iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[6] = ((u_short*)b->ipv6cp.myintid)[2];
                   1062:        iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[7] = ((u_short*)b->ipv6cp.myintid)[3];
                   1063:     } else {
                   1064:        u_addrcopy(&iface->conf.self_ipv6_addr, &iface->self_ipv6_addr);
                   1065:     }
                   1066:     if (ready && !iface->conf.peer_ipv6_addr_force) {
                   1067:         iface->peer_ipv6_addr.family = AF_INET6;
                   1068:         iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[0] = 0x80fe;  /* Network byte order */
                   1069:         iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[1] = 0x0000;
                   1070:         iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[2] = 0x0000;
                   1071:         iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[3] = 0x0000;
                   1072:         iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[4] = ((u_short*)b->ipv6cp.hisintid)[0];
                   1073:         iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[5] = ((u_short*)b->ipv6cp.hisintid)[1];
                   1074:         iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[6] = ((u_short*)b->ipv6cp.hisintid)[2];
                   1075:         iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[7] = ((u_short*)b->ipv6cp.hisintid)[3];
                   1076:     } else {
                   1077:        u_addrcopy(&iface->conf.peer_ipv6_addr, &iface->peer_ipv6_addr);
                   1078:     }
                   1079: 
                   1080:     if (IfaceNgIpv6Init(b, ready)) {
                   1081:         Log(LG_ERR, ("[%s] IFACE: IfaceNgIpv6Init() failed, closing IPv6CP", b->name));
                   1082:         FsmFailure(&b->ipv6cp.fsm, FAIL_NEGOT_FAILURE);
                   1083:         return (-1);
                   1084:     };
                   1085:   
                   1086:     /* Set addresses */
                   1087:     if (!u_addrempty(&iface->self_ipv6_addr)) {
                   1088:        struct u_range  rng;
                   1089:        rng.addr = iface->self_ipv6_addr;
                   1090:        rng.width = 64;
                   1091:        if (IfaceChangeAddr(b, 1, &rng, &iface->peer_ipv6_addr)) {
                   1092:            Log(LG_ERR, ("[%s] IFACE: IfaceChangeAddr() failed, closing IPv6CP", b->name));
                   1093:            FsmFailure(&b->ipv6cp.fsm, FAIL_NEGOT_FAILURE);
                   1094:            return (-1);
                   1095:        }
                   1096:     };
                   1097:   
                   1098:     /* Add static routes */
                   1099:     SLIST_FOREACH(r, &iface->routes, next) {
                   1100:        if (u_rangefamily(&r->dest)==AF_INET6) {
                   1101:            r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_ipv6_addr) == 0);
                   1102:        }
                   1103:     }
                   1104:     /* Add dynamic routes */
                   1105:     SLIST_FOREACH(r, &b->params.routes, next) {
                   1106:        if (u_rangefamily(&r->dest)==AF_INET6) {
                   1107:            r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_ipv6_addr) == 0);
                   1108:        }
                   1109:     }
                   1110: 
                   1111:     /* Call "up" script */
                   1112:     if (*iface->up_script) {
                   1113:        char    selfbuf[48],peerbuf[48];
                   1114:        int     res;
                   1115: 
                   1116:        res = ExecCmd(LG_IFACE2, b->name, "%s %s inet6 %s%%%s %s%%%s '%s' '%s'",
                   1117:            iface->up_script, iface->ifname, 
                   1118:            u_addrtoa(&iface->self_ipv6_addr, selfbuf, sizeof(selfbuf)), iface->ifname,
                   1119:            u_addrtoa(&iface->peer_ipv6_addr, peerbuf, sizeof(peerbuf)), iface->ifname, 
                   1120:            *b->params.authname ? b->params.authname : "-",
                   1121:            *b->params.peeraddr ? b->params.peeraddr : "-");
                   1122:        if (res != 0) {
                   1123:            FsmFailure(&b->ipv6cp.fsm, FAIL_NEGOT_FAILURE);
                   1124:            return (-1);
                   1125:        }
                   1126:     }
                   1127:     return (0);
                   1128: 
                   1129: }
                   1130: 
                   1131: /*
                   1132:  * IfaceIpv6IfaceDown()
                   1133:  *
                   1134:  * Bring down the IPv6 interface. This implies we're no longer ready.
                   1135:  */
                   1136: 
                   1137: void
                   1138: IfaceIpv6IfaceDown(Bund b)
                   1139: {
                   1140:     IfaceState         const iface = &b->iface;
                   1141:     IfaceRoute         r;
                   1142:     struct u_range     rng;
                   1143: 
                   1144:     /* Call "down" script */
                   1145:     if (*iface->down_script) {
                   1146:        char    selfbuf[48],peerbuf[48];
                   1147: 
                   1148:        ExecCmd(LG_IFACE2, b->name, "%s %s inet6 %s%%%s %s%%%s '%s' '%s'",
                   1149:            iface->down_script, iface->ifname, 
                   1150:            u_addrtoa(&iface->self_ipv6_addr, selfbuf, sizeof(selfbuf)), iface->ifname,
                   1151:            u_addrtoa(&iface->peer_ipv6_addr, peerbuf, sizeof(peerbuf)), iface->ifname, 
                   1152:            *b->params.authname ? b->params.authname : "-",
                   1153:            *b->params.peeraddr ? b->params.peeraddr : "-");
                   1154:     }
                   1155: 
                   1156:     /* Delete dynamic routes */
                   1157:     SLIST_FOREACH(r, &b->params.routes, next) {
                   1158:        if (u_rangefamily(&r->dest)==AF_INET6) {
                   1159:            if (!r->ok)
                   1160:                continue;
                   1161:            IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_ipv6_addr);
                   1162:            r->ok = 0;
                   1163:        }
                   1164:     }
                   1165:     /* Delete static routes */
                   1166:     SLIST_FOREACH(r, &iface->routes, next) {
                   1167:        if (u_rangefamily(&r->dest)==AF_INET6) {
                   1168:            if (!r->ok)
                   1169:                continue;
                   1170:            IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_ipv6_addr);
                   1171:            r->ok = 0;
                   1172:        }
                   1173:     }
                   1174: 
                   1175:     if (!u_addrempty(&iface->self_ipv6_addr)) {
                   1176:        /* Remove address from interface */
                   1177:        rng.addr = iface->self_ipv6_addr;
                   1178:        rng.width = 64;
                   1179:        IfaceChangeAddr(b, 0, &rng, &iface->peer_ipv6_addr);
                   1180:     }
                   1181: 
                   1182:     IfaceNgIpv6Shutdown(b);
                   1183: }
                   1184: 
                   1185: /*
                   1186:  * IfaceIdleTimeout()
                   1187:  */
                   1188: 
                   1189: static void
                   1190: IfaceIdleTimeout(void *arg)
                   1191: {
                   1192:     Bund b = (Bund)arg;
                   1193: 
                   1194:   IfaceState                   const iface = &b->iface;
                   1195:   int                          k;
                   1196: 
                   1197:   /* Get updated bpf node traffic statistics */
                   1198:   BundUpdateStats(b);
                   1199: 
                   1200:   /* Mark current traffic period if there was traffic */
                   1201:   if (iface->idleStats.recvFrames + iface->idleStats.xmitFrames < 
                   1202:        b->stats.recvFrames + b->stats.xmitFrames) {
                   1203:     iface->traffic[0] = TRUE;
                   1204:   } else {             /* no demand traffic for a whole idle timeout period? */
                   1205:     for (k = 0; k < IFACE_IDLE_SPLIT && !iface->traffic[k]; k++);
                   1206:     if (k == IFACE_IDLE_SPLIT) {
                   1207:       Log(LG_BUND, ("[%s] IFACE: Idle timeout", b->name));
                   1208:       RecordLinkUpDownReason(b, NULL, 0, STR_IDLE_TIMEOUT, NULL);
                   1209:       BundClose(b);
                   1210:       return;
                   1211:     }
                   1212:   }
                   1213: 
                   1214:   iface->idleStats = b->stats;
                   1215: 
                   1216:   /* Shift traffic history */
                   1217:   memmove(iface->traffic + 1,
                   1218:     iface->traffic, (IFACE_IDLE_SPLIT - 1) * sizeof(*iface->traffic));
                   1219:   iface->traffic[0] = FALSE;
                   1220: 
                   1221:   /* Restart timer */
                   1222:   TimerStart(&iface->idleTimer);
                   1223: }
                   1224: 
                   1225: /*
                   1226:  * IfaceSessionTimeout()
                   1227:  */
                   1228: 
                   1229: static void
                   1230: IfaceSessionTimeout(void *arg)
                   1231: {
                   1232:     Bund b = (Bund)arg;
                   1233: 
                   1234:   Log(LG_BUND, ("[%s] IFACE: Session timeout", b->name));
                   1235: 
                   1236:   RecordLinkUpDownReason(b, NULL, 0, STR_SESSION_TIMEOUT, NULL);
                   1237: 
                   1238:   BundClose(b);
                   1239: 
                   1240: }
                   1241: 
                   1242: /*
                   1243:  * IfaceCachePkt()
                   1244:  *
                   1245:  * A packet caused dial-on-demand; save it for later if possible.
                   1246:  * Consumes the mbuf in any case.
                   1247:  */
                   1248: 
                   1249: static void
                   1250: IfaceCachePkt(Bund b, int proto, Mbuf pkt)
                   1251: {
                   1252:     IfaceState const iface = &b->iface;
                   1253: 
                   1254:     /* Only cache network layer data */
                   1255:     if (!PROT_NETWORK_DATA(proto)) {
                   1256:        mbfree(pkt);
                   1257:        return;
                   1258:     }
                   1259: 
                   1260:     /* Release previously cached packet, if any, and save this one */
                   1261:     if (iface->dodCache.pkt)
                   1262:        mbfree(iface->dodCache.pkt);
                   1263: 
                   1264:     iface->dodCache.pkt = pkt;
                   1265:     iface->dodCache.proto = proto;
                   1266:     iface->dodCache.ts = time(NULL);
                   1267: }
                   1268: 
                   1269: /*
                   1270:  * IfaceCacheSend()
                   1271:  *
                   1272:  * Send cached packet
                   1273:  */
                   1274: 
                   1275: static void
                   1276: IfaceCacheSend(Bund b)
                   1277: {
                   1278:     IfaceState const iface = &b->iface;
                   1279: 
                   1280:     if (iface->dodCache.pkt) {
                   1281:        if (iface->dodCache.ts + MAX_DOD_CACHE_DELAY < time(NULL))
                   1282:            mbfree(iface->dodCache.pkt);
                   1283:        else {
                   1284:            if (NgFuncWritePppFrame(b, NG_PPP_BUNDLE_LINKNUM,
                   1285:                    iface->dodCache.proto, iface->dodCache.pkt) < 0) {
                   1286:                Perror("[%s] can't write cached pkt", b->name);
                   1287:            }
                   1288:        }
                   1289:        iface->dodCache.pkt = NULL;
                   1290:     }
                   1291: }
                   1292: 
                   1293: /*
                   1294:  * IfaceIsDemand()
                   1295:  *
                   1296:  * Determine if this outgoing packet qualifies for dial-on-demand
                   1297:  */
                   1298: 
                   1299: static int
                   1300: IfaceIsDemand(int proto, Mbuf pkt)
                   1301: {
                   1302:   switch (proto) {
                   1303:     case PROTO_IP:
                   1304:       {
                   1305:         struct ip      *ip;
                   1306: 
                   1307:         if (MBLEN(pkt) < sizeof(struct ip))
                   1308:            return (0);
                   1309: 
                   1310:        ip = (struct ip *)MBDATA(pkt);
                   1311:        switch (ip->ip_p) {
                   1312:          case IPPROTO_IGMP:            /* No multicast stuff */
                   1313:            return(0);
                   1314: #if (!defined(__FreeBSD__) || __FreeBSD_version >= 600025)
                   1315:          case IPPROTO_ICMP:
                   1316:            {
                   1317:              struct icmphdr    *icmp;
                   1318:              
                   1319:              if (MBLEN(pkt) < (ip->ip_hl * 4 + sizeof(struct icmphdr)))
                   1320:                return (0);
                   1321: 
                   1322:              icmp = (struct icmphdr *) ((u_int32_t *) ip + ip->ip_hl);
                   1323: 
                   1324:              switch (icmp->icmp_type)  /* No ICMP replies */
                   1325:              {
                   1326:                case ICMP_ECHOREPLY:
                   1327:                case ICMP_UNREACH:
                   1328:                case ICMP_REDIRECT:
                   1329:                  return(0);
                   1330:                default:
                   1331:                  break;
                   1332:              }
                   1333:            }
                   1334:            break;
                   1335: #endif
                   1336:          case IPPROTO_UDP:
                   1337:            {
                   1338:              struct udphdr     *udp;
                   1339: 
                   1340:              if (MBLEN(pkt) < (ip->ip_hl * 4 + sizeof(struct udphdr)))
                   1341:                return (0);
                   1342: 
                   1343:              udp = (struct udphdr *) ((u_int32_t *) ip + ip->ip_hl);
                   1344: 
                   1345: #define NTP_PORT       123
                   1346:              if (ntohs(udp->uh_dport) == NTP_PORT)     /* No NTP packets */
                   1347:                return(0);
                   1348:            }
                   1349:            break;
                   1350:          case IPPROTO_TCP:
                   1351:            {
                   1352:              struct tcphdr     *tcp;
                   1353: 
                   1354:              if (MBLEN(pkt) < (ip->ip_hl * 4 + sizeof(struct tcphdr)))
                   1355:                return (0);
                   1356: 
                   1357:              tcp = (struct tcphdr *) ((u_int32_t *) ip + ip->ip_hl);
                   1358: 
                   1359:              if (tcp->th_flags & TH_RST)       /* No TCP reset packets */
                   1360:                return(0);
                   1361:            }
                   1362:            break;
                   1363:          default:
                   1364:            break;
                   1365:        }
                   1366:        break;
                   1367:       }
                   1368:     default:
                   1369:       break;
                   1370:   }
                   1371:   return(1);
                   1372: }
                   1373: 
                   1374: /*
                   1375:  * IfaceSetCommand()
                   1376:  */
                   1377: 
                   1378: static int
                   1379: IfaceSetCommand(Context ctx, int ac, char *av[], void *arg)
                   1380: {
                   1381:   IfaceState   const iface = &ctx->bund->iface;
                   1382:   int          empty_arg;
                   1383: 
                   1384:   switch ((intptr_t)arg) {
                   1385:     case SET_NAME:
                   1386: #ifdef SIOCSIFDESCR
                   1387:     case SET_DESCR:
                   1388: #endif
                   1389:     case SET_UP_SCRIPT:
                   1390:     case SET_DOWN_SCRIPT:
                   1391:       empty_arg = TRUE;
                   1392:       break;
                   1393:     default:
                   1394:       empty_arg = FALSE;
                   1395:       break;
                   1396:   }
                   1397: 
                   1398:   if ((ac == 0) && (empty_arg == FALSE))
                   1399:     return(-1);
                   1400:   switch ((intptr_t)arg) {
                   1401:     case SET_IDLE:
                   1402:       iface->idle_timeout = atoi(*av);
                   1403:       break;
                   1404:     case SET_SESSION:
                   1405:       iface->session_timeout = atoi(*av);
                   1406:       break;
                   1407:     case SET_ADDRS:
                   1408:       {
                   1409:        struct u_range  self_addr;
                   1410:        struct u_addr   peer_addr;
                   1411:        int     self_addr_force = 0, peer_addr_force = 0;
                   1412:        char    *arg;
                   1413: 
                   1414:        /* Parse */
                   1415:        if (ac != 2)
                   1416:          return(-1);
                   1417:        arg = av[0];
                   1418:        if (arg[0] == '!') {
                   1419:            self_addr_force = 1;
                   1420:            arg++;
                   1421:        }
                   1422:        if (!ParseRange(arg, &self_addr, ALLOW_IPV4|ALLOW_IPV6))
                   1423:          Error("Bad IP address \"%s\"", av[0]);
                   1424:        arg = av[1];
                   1425:        if (arg[0] == '!') {
                   1426:            peer_addr_force = 1;
                   1427:            arg++;
                   1428:        }
                   1429:        if (!ParseAddr(arg, &peer_addr, ALLOW_IPV4|ALLOW_IPV6))
                   1430:          Error("Bad IP address \"%s\"", av[1]);
                   1431:        if (self_addr.addr.family != peer_addr.family)
                   1432:          Error("Addresses must be from the same protocol family");
                   1433: 
                   1434:        /* OK */
                   1435:        if (peer_addr.family == AF_INET) {
                   1436:            iface->conf.self_addr = self_addr;
                   1437:            iface->conf.peer_addr = peer_addr;
                   1438:            iface->conf.self_addr_force = self_addr_force;
                   1439:            iface->conf.peer_addr_force = peer_addr_force;
                   1440:        } else {
                   1441:            iface->conf.self_ipv6_addr = self_addr.addr;
                   1442:            iface->conf.peer_ipv6_addr = peer_addr;
                   1443:            iface->conf.self_ipv6_addr_force = self_addr_force;
                   1444:            iface->conf.peer_ipv6_addr_force = peer_addr_force;
                   1445:        }
                   1446:       }
                   1447:       break;
                   1448: 
                   1449:     case SET_ROUTE:
                   1450:       {
                   1451:        struct u_range          range;
                   1452:        IfaceRoute              r;
                   1453: 
                   1454:        /* Check */
                   1455:        if (ac != 1)
                   1456:          return(-1);
                   1457: 
                   1458:        /* Get dest address */
                   1459:        if (!strcasecmp(av[0], "default")) {
                   1460:          u_rangeclear(&range);
                   1461:          range.addr.family=AF_INET;
                   1462:        }
                   1463:        else if (!ParseRange(av[0], &range, ALLOW_IPV4|ALLOW_IPV6))
                   1464:          Error("Bad route dest address \"%s\"", av[0]);
                   1465:        r = Malloc(MB_IFACE, sizeof(struct ifaceroute));
                   1466:        r->dest = range;
                   1467:        r->ok = 0;
                   1468:        SLIST_INSERT_HEAD(&iface->routes, r, next);
                   1469:       }
                   1470:       break;
                   1471: 
                   1472:     case SET_MTU:
                   1473:       {
                   1474:        int     max_mtu;
                   1475: 
                   1476:        /* Check */
                   1477:        if (ac != 1)
                   1478:          return(-1);
                   1479: 
                   1480:        max_mtu = atoi(av[0]);
                   1481:        if (max_mtu < IFACE_MIN_MTU || max_mtu > IFACE_MAX_MTU)
                   1482:          Error("Invalid interface mtu %d", max_mtu);
                   1483:        iface->max_mtu = max_mtu;
                   1484:       }
                   1485:       break;
                   1486: 
                   1487:     case SET_NAME:
                   1488:        switch (ac) {
                   1489:          case 0:
                   1490:            /* Restore original interface name */
                   1491:            if (strcmp(iface->ifname, iface->ngname) != 0) {
                   1492:                iface->conf.ifname[0] = '\0';
                   1493:                return IfaceSetName(ctx->bund, iface->ngname);
                   1494:            }
                   1495:            break;
                   1496:          case 1:
                   1497:            if (strcmp(iface->ifname, av[0]) != 0) {
                   1498:                int ifmaxlen = IF_NAMESIZE - ctx->bund->tmpl * IFNUMLEN;
                   1499:                if (strlen(av[0]) >= ifmaxlen)
                   1500:                    Error("Interface name too long, >%d characters", ifmaxlen-1);
                   1501:                if ((strncmp(av[0], "ng", 2) == 0) &&
                   1502:                  ((ctx->bund->tmpl && av[0][2] == 0) ||
                   1503:                  (av[0][2] >= '0' && av[0][2] <= '9')))
                   1504:                    Error("This interface name is reserved");
                   1505:                strlcpy(iface->conf.ifname, av[0], sizeof(iface->conf.ifname));
                   1506:                return IfaceSetName(ctx->bund, av[0]);
                   1507:            }
                   1508:            break;
                   1509:          default:
                   1510:            return(-1);
                   1511:        }
                   1512:        break;
                   1513: #ifdef SIOCSIFDESCR
                   1514:     case SET_DESCR:
                   1515:        if (ctx->bund->tmpl)
                   1516:            Error("Impossible to apply on template");
                   1517:        if (iface->conf.ifdescr != NULL)
                   1518:            Freee(iface->conf.ifdescr);
                   1519:        iface->conf.ifdescr = NULL;
                   1520:        iface->ifdescr = NULL;
                   1521:        switch (ac) {
                   1522:          case 0:
                   1523:            return IfaceSetDescr(ctx->bund, "");
                   1524:            break;
                   1525:          case 1:
                   1526:            iface->conf.ifdescr = Mstrdup(MB_IFACE, av[0]);
                   1527:            if (IfaceSetDescr(ctx->bund, av[0]) == 0) {
                   1528:                iface->ifdescr = iface->conf.ifdescr;
                   1529:                return(0);
                   1530:            } else
                   1531:                return(-1);
                   1532:            break;
                   1533:          default:
                   1534:            return(-1);
                   1535:        }
                   1536:        break;
                   1537: #endif
                   1538: #ifdef SIOCAIFGROUP
                   1539:     case SET_GROUP:
                   1540:        if (ac != 1)
                   1541:          return(-1);
                   1542: 
                   1543:        if (av[0][0] && isdigit(av[0][strlen(av[0]) - 1]))
                   1544:            Error("Groupnames may not end in a digit");
                   1545:        if (strlen(av[0]) >= IFNAMSIZ)
                   1546:            Error("Group name %s too long", av[0]);
                   1547:        if (iface->conf.ifgroup[0] != 0)
                   1548:            IfaceDelGroup(ctx->bund, iface->conf.ifgroup);
                   1549:        strlcpy(iface->conf.ifgroup, av[0], IFNAMSIZ);
                   1550:        return IfaceAddGroup(ctx->bund, av[0]);
                   1551:       break;
                   1552: #endif
                   1553:     case SET_UP_SCRIPT:
                   1554:       switch (ac) {
                   1555:        case 0:
                   1556:          *iface->up_script = 0;
                   1557:          break;
                   1558:        case 1:
                   1559:          strlcpy(iface->up_script, av[0], sizeof(iface->up_script));
                   1560:          break;
                   1561:        default:
                   1562:          return(-1);
                   1563:       }
                   1564:       break;
                   1565: 
                   1566:     case SET_DOWN_SCRIPT:
                   1567:       switch (ac) {
                   1568:        case 0:
                   1569:          *iface->down_script = 0;
                   1570:          break;
                   1571:        case 1:
                   1572:          strlcpy(iface->down_script, av[0], sizeof(iface->down_script));
                   1573:          break;
                   1574:        default:
                   1575:          return(-1);
                   1576:       }
                   1577:       break;
                   1578: 
                   1579:     case SET_ENABLE:
                   1580:       EnableCommand(ac, av, &iface->options, gConfList);
                   1581:       break;
                   1582: 
                   1583:     case SET_DISABLE:
                   1584:       DisableCommand(ac, av, &iface->options, gConfList);
                   1585:       break;
                   1586: 
                   1587:     default:
                   1588:       assert(0);
                   1589:   }
                   1590:   return(0);
                   1591: }
                   1592: 
                   1593: /*
                   1594:  * IfaceStat()
                   1595:  */
                   1596: 
                   1597: int
                   1598: IfaceStat(Context ctx, int ac, char *av[], void *arg)
                   1599: {
                   1600:     Bund       const b = ctx->bund;
                   1601:     IfaceState const iface = &b->iface;
                   1602:     IfaceRoute r;
                   1603: #ifdef USE_NG_BPF
                   1604:     int                k;
                   1605: #endif
                   1606:     char       buf[48];
                   1607: #if defined(USE_NG_BPF) || defined(USE_IPFW)
                   1608:     struct acl *a;
                   1609: #endif
                   1610: 
                   1611:     Printf("Interface configuration:\r\n");
                   1612:     Printf("\tName            : %s\r\n", iface->conf.ifname);
                   1613: #ifdef SIOCSIFDESCR
                   1614:     Printf("\tDescription     : \"%s\"\r\n",
                   1615:        (iface->conf.ifdescr != NULL) ? iface->conf.ifdescr : "<none>");
                   1616: #endif
                   1617: #ifdef SIOCAIFGROUP
                   1618:     Printf("\tGroup           : %s\r\n", iface->conf.ifgroup);
                   1619: #endif
                   1620:     Printf("\tMaximum MTU     : %d bytes\r\n", iface->max_mtu);
                   1621:     Printf("\tIdle timeout    : %d seconds\r\n", iface->idle_timeout);
                   1622:     Printf("\tSession timeout : %d seconds\r\n", iface->session_timeout);
                   1623:     if (!u_rangeempty(&iface->conf.self_addr)) {
                   1624:        Printf("\tIP Addresses    : %s%s -> ", iface->conf.self_addr_force?"!":"",
                   1625:            u_rangetoa(&iface->conf.self_addr,buf,sizeof(buf)));
                   1626:        Printf("%s%s\r\n",  iface->conf.peer_addr_force?"!":"",
                   1627:            u_addrtoa(&iface->conf.peer_addr,buf,sizeof(buf)));
                   1628:     }
                   1629:     if (!u_addrempty(&iface->conf.self_ipv6_addr)) {
                   1630:        Printf("\tIPv6 Addresses  : %s%s%%%s -> ",  iface->conf.self_ipv6_addr_force?"!":"",
                   1631:            u_addrtoa(&iface->conf.self_ipv6_addr,buf,sizeof(buf)), iface->ifname);
                   1632:        Printf("%s%s%%%s\r\n",  iface->conf.peer_ipv6_addr_force?"!":"",
                   1633:            u_addrtoa(&iface->conf.peer_ipv6_addr,buf,sizeof(buf)), iface->ifname);
                   1634:     }
                   1635:     Printf("\tEvent scripts\r\n");
                   1636:     Printf("\t  up-script     : \"%s\"\r\n",
                   1637:        *iface->up_script ? iface->up_script : "<none>");
                   1638:     Printf("\t  down-script   : \"%s\"\r\n",
                   1639:        *iface->down_script ? iface->down_script : "<none>");
                   1640:     Printf("Interface options:\r\n");
                   1641:     OptStat(ctx, &iface->options, gConfList);
                   1642:     if (!SLIST_EMPTY(&iface->routes)) {
                   1643:        Printf("Static routes via peer:\r\n");
                   1644:        SLIST_FOREACH(r, &iface->routes, next) {
                   1645:            Printf("\t%s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf)));
                   1646:        }
                   1647:     }
                   1648:     Printf("Interface status:\r\n");
                   1649:     Printf("\tAdmin status    : %s\r\n", iface->open ? "OPEN" : "CLOSED");
                   1650:     Printf("\tStatus          : %s\r\n", iface->up ? (iface->dod?"DoD":"UP") : "DOWN");
                   1651:     Printf("\tName            : %s\r\n", iface->ifname);
                   1652: #ifdef SIOCSIFDESCR
                   1653:     Printf("\tDescription     : \"%s\"\r\n",
                   1654:        (iface->ifdescr != NULL) ? iface->ifdescr : "<none>");
                   1655: #endif
                   1656:     if (iface->up) {
                   1657:        Printf("\tSession time    : %ld seconds\r\n", (long int)(time(NULL) - iface->last_up));
                   1658:        if (b->params.idle_timeout || iface->idle_timeout)
                   1659:            Printf("\tIdle timeout    : %d seconds\r\n", b->params.idle_timeout?b->params.idle_timeout:iface->idle_timeout);
                   1660:        if (b->params.session_timeout || iface->session_timeout)
                   1661:            Printf("\tSession timeout : %d seconds\r\n", b->params.session_timeout?b->params.session_timeout:iface->session_timeout);
                   1662:        Printf("\tMTU             : %d bytes\r\n", iface->mtu);
                   1663:     }
                   1664:     if (iface->ip_up && !u_rangeempty(&iface->self_addr)) {
                   1665:        Printf("\tIP Addresses    : %s -> ", u_rangetoa(&iface->self_addr,buf,sizeof(buf)));
                   1666:        Printf("%s\r\n", u_addrtoa(&iface->peer_addr,buf,sizeof(buf)));
                   1667:     }
                   1668:     if (iface->ipv6_up && !u_addrempty(&iface->self_ipv6_addr)) {
                   1669:        Printf("\tIPv6 Addresses  : %s%%%s -> ", 
                   1670:            u_addrtoa(&iface->self_ipv6_addr,buf,sizeof(buf)), iface->ifname);
                   1671:        Printf("%s%%%s\r\n", u_addrtoa(&iface->peer_ipv6_addr,buf,sizeof(buf)), iface->ifname);
                   1672:     }
                   1673:     if (iface->up) {
                   1674:         Printf("Dynamic routes via peer:\r\n");
                   1675:        SLIST_FOREACH(r, &ctx->bund->params.routes, next) {
                   1676:            Printf("\t%s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf)));
                   1677:        }
                   1678: #ifdef USE_IPFW
                   1679:        Printf("IPFW pipes:\r\n");
                   1680:        a = ctx->bund->params.acl_pipe;
                   1681:        while (a) {
                   1682:            Printf("\t%d (%d)\t: '%s'\r\n", a->number, a->real_number, a->rule);
                   1683:            a = a->next;
                   1684:        }
                   1685:        Printf("IPFW queues:\r\n");
                   1686:        a = ctx->bund->params.acl_queue;
                   1687:        while (a) {
                   1688:            Printf("\t%d (%d)\t: '%s'\r\n", a->number, a->real_number, a->rule);
                   1689:            a = a->next;
                   1690:        }
                   1691:        Printf("IPFW tables:\r\n");
                   1692:        a = ctx->bund->params.acl_table;
                   1693:        while (a) {
                   1694:            if (a->number != 0)
                   1695:                Printf("\t%d (%d)\t: '%s'\r\n", a->number, a->real_number, a->rule);
                   1696:            else
                   1697:                Printf("\t(%d)\t: '%s'\r\n", a->real_number, a->rule);
                   1698:            a = a->next;
                   1699:        }
                   1700:        Printf("IPFW rules:\r\n");
                   1701:        a = ctx->bund->params.acl_rule;
                   1702:        while (a) {
                   1703:            Printf("\t%d (%d)\t: '%s'\r\n", a->number, a->real_number, a->rule);
                   1704:            a = a->next;
                   1705:        }
                   1706: #endif /* USE_IPFW */
                   1707: #ifdef USE_NG_BPF
                   1708:        Printf("Traffic filters:\r\n");
                   1709:        for (k = 0; k < ACL_FILTERS; k++) {
                   1710:            a = ctx->bund->params.acl_filters[k];
                   1711:            if (a == NULL)
                   1712:                a = acl_filters[k];
                   1713:            while (a) {
                   1714:                Printf("\t%d#%d\t: '%s'\r\n", (k + 1), a->number, a->rule);
                   1715:                a = a->next;
                   1716:            }
                   1717:        }
                   1718:        Printf("Traffic limits:\r\n");
                   1719:        for (k = 0; k < 2; k++) {
                   1720:            a = ctx->bund->params.acl_limits[k];
                   1721:            while (a) {
                   1722:                Printf("\t%s#%d%s%s\t: '%s'\r\n", (k?"out":"in"), a->number,
                   1723:                    ((a->name[0])?"#":""), a->name, a->rule);
                   1724:                a = a->next;
                   1725:            }
                   1726:        }
                   1727: #endif /* USE_NG_BPF */
                   1728:     }
                   1729:     return(0);
                   1730: }
                   1731: 
                   1732: /*
                   1733:  * IfaceSetMTU()
                   1734:  *
                   1735:  * Set MTU and bandwidth on bundle's interface
                   1736:  */
                   1737: 
                   1738: void
                   1739: IfaceSetMTU(Bund b, int mtu)
                   1740: {
                   1741:     IfaceState         const iface = &b->iface;
                   1742:     struct ifreq       ifr;
                   1743:     int                        s;
                   1744: 
                   1745:     /* Get socket */
                   1746:     if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                   1747:        Perror("[%s] IFACE: Can't get socket to set MTU", b->name);
                   1748:        return;
                   1749:     }
                   1750: 
                   1751:     if ((b->params.mtu > 0) && (mtu > b->params.mtu)) {
                   1752:        mtu = b->params.mtu;
                   1753:        Log(LG_IFACE2, ("[%s] IFACE: forcing MTU of auth backend: %d bytes",
                   1754:            b->name, mtu));
                   1755:     }
                   1756: 
                   1757:     /* Limit MTU to configured maximum */
                   1758:     if (mtu > iface->max_mtu)
                   1759:         mtu = iface->max_mtu;
                   1760: 
                   1761:     /* Set MTU on interface */
                   1762:     memset(&ifr, 0, sizeof(ifr));
                   1763:     strlcpy(ifr.ifr_name, b->iface.ifname, sizeof(ifr.ifr_name));
                   1764:     ifr.ifr_mtu = mtu;
                   1765:     Log(LG_IFACE2, ("[%s] IFACE: setting %s MTU to %d bytes",
                   1766:        b->name, b->iface.ifname, mtu));
                   1767:     if (ioctl(s, SIOCSIFMTU, (char *)&ifr) < 0)
                   1768:        Perror("[%s] IFACE: ioctl(%s, %s)", b->name, b->iface.ifname, "SIOCSIFMTU");
                   1769:     close(s);
                   1770: 
                   1771:     /* Save MTU */
                   1772:     iface->mtu = mtu;
                   1773: 
                   1774: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
                   1775:     /* Update tcpmssfix config */
                   1776:     if (iface->mss_up)
                   1777:         IfaceSetupMSS(b, MAXMSS(mtu));
                   1778: #endif
                   1779: 
                   1780: }
                   1781: 
                   1782: void
                   1783: IfaceChangeFlags(Bund b, int clear, int set)
                   1784: {
                   1785:     struct ifreq ifrq;
                   1786:     int s, new_flags;
                   1787: 
                   1788:     Log(LG_IFACE2, ("[%s] IFACE: Change interface flags: -%d +%d",
                   1789:        b->name, clear, set)); 
                   1790: 
                   1791:     if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                   1792:        Perror("[%s] IFACE: Can't get socket to change interface flags", b->name);
                   1793:        return;
                   1794:     }
                   1795: 
                   1796:     memset(&ifrq, '\0', sizeof(ifrq));
                   1797:     strlcpy(ifrq.ifr_name, b->iface.ifname, sizeof(ifrq.ifr_name));
                   1798:     ifrq.ifr_name[sizeof(ifrq.ifr_name) - 1] = '\0';
                   1799:     if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
                   1800:        Perror("[%s] IFACE: ioctl(%s, %s)", b->name, b->iface.ifname, "SIOCGIFFLAGS");
                   1801:        close(s);
                   1802:        return;
                   1803:     }
                   1804:     new_flags = (ifrq.ifr_flags & 0xffff) | (ifrq.ifr_flagshigh << 16);
                   1805: 
                   1806:     new_flags &= ~clear;
                   1807:     new_flags |= set;
                   1808: 
                   1809:     ifrq.ifr_flags = new_flags & 0xffff;
                   1810:     ifrq.ifr_flagshigh = new_flags >> 16;
                   1811: 
                   1812:     if (ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
                   1813:        Perror("[%s] IFACE: ioctl(%s, %s)", b->name, b->iface.ifname, "SIOCSIFFLAGS");
                   1814:        close(s);
                   1815:        return;
                   1816:     }
                   1817:     close(s);
                   1818: }
                   1819: 
                   1820: #if defined(__KAME__) && !defined(NOINET6)
                   1821: static void
                   1822: add_scope(struct sockaddr *sa, int ifindex)
                   1823: {
                   1824:   struct sockaddr_in6 *sa6;
                   1825: 
                   1826:   if (sa->sa_family != AF_INET6)
                   1827:     return;
                   1828:   sa6 = (struct sockaddr_in6 *)sa;
                   1829:   if (!IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) &&
                   1830:       !IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr))
                   1831:     return;
                   1832:   if (*(u_int16_t *)&sa6->sin6_addr.s6_addr[2] != 0)
                   1833:     return;
                   1834:   *(u_int16_t *)&sa6->sin6_addr.s6_addr[2] = htons(ifindex);
                   1835: }
                   1836: #endif
                   1837: 
                   1838: int
                   1839: IfaceChangeAddr(Bund b, int add, struct u_range *self, struct u_addr *peer)
                   1840: {
                   1841:     struct ifaliasreq ifra;
                   1842:     struct in6_aliasreq ifra6;
                   1843:     struct sockaddr_in *me4, *msk4, *peer4;
                   1844:     struct sockaddr_storage ssself, sspeer, ssmsk;
                   1845:     int res = 0;
                   1846:     int s;
                   1847:     char buf[48], buf1[48];
                   1848: 
                   1849:     Log(LG_IFACE2, ("[%s] IFACE: %s address %s->%s %s %s",
                   1850:        b->name, add?"Add":"Remove", u_rangetoa(self, buf, sizeof(buf)), 
                   1851:        ((peer != NULL)?u_addrtoa(peer, buf1, sizeof(buf1)):""),
                   1852:        add?"to":"from", b->iface.ifname));
                   1853: 
                   1854:     u_rangetosockaddrs(self, &ssself, &ssmsk);
                   1855:     if (peer)
                   1856:        u_addrtosockaddr(peer, 0, &sspeer);
                   1857: 
                   1858:     if ((s = socket(self->addr.family, SOCK_DGRAM, 0)) < 0) {
                   1859:        Perror("[%s] IFACE: Can't get socket to change interface address", b->name);
                   1860:        return (s);
                   1861:     }
                   1862: 
                   1863:     switch (self->addr.family) {
                   1864:       case AF_INET:
                   1865:        memset(&ifra, '\0', sizeof(ifra));
                   1866:        strlcpy(ifra.ifra_name, b->iface.ifname, sizeof(ifra.ifra_name));
                   1867: 
                   1868:        me4 = (struct sockaddr_in *)&ifra.ifra_addr;
                   1869:        memcpy(me4, &ssself, sizeof(*me4));
                   1870: 
                   1871:        msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
                   1872:        memcpy(msk4, &ssmsk, sizeof(*msk4));
                   1873: 
                   1874:        peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
                   1875:        if (peer == NULL || peer->family == AF_UNSPEC) {
                   1876:            peer4->sin_family = AF_INET;
                   1877:            peer4->sin_len = sizeof(*peer4);
                   1878:            peer4->sin_addr.s_addr = INADDR_NONE;
                   1879:        } else
                   1880:            memcpy(peer4, &sspeer, sizeof(*peer4));
                   1881: 
                   1882:        res = ioctl(s, add?SIOCAIFADDR:SIOCDIFADDR, &ifra);
                   1883:        if (res == -1) {
                   1884:            Perror("[%s] IFACE: %s IPv4 address %s %s failed", 
                   1885:                b->name, add?"Adding":"Removing", add?"to":"from", b->iface.ifname);
                   1886:        }
                   1887:        break;
                   1888: 
                   1889:       case AF_INET6:
                   1890:        memset(&ifra6, '\0', sizeof(ifra6));
                   1891:        strlcpy(ifra6.ifra_name, b->iface.ifname, sizeof(ifra6.ifra_name));
                   1892: 
                   1893:        memcpy(&ifra6.ifra_addr, &ssself, sizeof(ifra6.ifra_addr));
                   1894:        memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof(ifra6.ifra_prefixmask));
                   1895:        if (peer == NULL || peer->family == AF_UNSPEC)
                   1896:            ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
                   1897:        else if (memcmp(&((struct sockaddr_in6 *)&ssmsk)->sin6_addr, &in6mask128,
                   1898:                    sizeof(in6mask128)) == 0)
                   1899:            memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof(ifra6.ifra_dstaddr));
                   1900:        ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
                   1901:        ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
                   1902: 
                   1903:        res = ioctl(s, add?SIOCAIFADDR_IN6:SIOCDIFADDR_IN6, &ifra6);
                   1904:        if (res == -1) {
                   1905:            Perror("[%s] IFACE: %s IPv6 address %s %s failed", 
                   1906:                b->name, add?"Adding":"Removing", add?"to":"from", b->iface.ifname);
                   1907:        }
                   1908:        break;
                   1909: 
                   1910:       default:
                   1911:         res = -1;
                   1912:        break;
                   1913:     }
                   1914:     close(s);
                   1915:     return (res);
                   1916: }
                   1917: 
                   1918: struct rtmsg {
                   1919:   struct rt_msghdr m_rtm;
                   1920:   char m_space[256];
                   1921: };
                   1922: 
                   1923: static size_t
                   1924: memcpy_roundup(char *cp, const void *data, size_t len)
                   1925: {
                   1926:   size_t padlen;
                   1927: 
                   1928: #define ROUNDUP(x) ((x) ? (1 + (((x) - 1) | (sizeof(long) - 1))) : sizeof(long))
                   1929:   padlen = ROUNDUP(len);
                   1930:   memcpy(cp, data, len);
                   1931:   if (padlen > len)
                   1932:     memset(cp + len, '\0', padlen - len);
                   1933: 
                   1934:   return padlen;
                   1935: }
                   1936: 
                   1937: int
                   1938: IfaceSetRoute(Bund b, int cmd, struct u_range *dst,
                   1939:        struct u_addr *gw)
                   1940: {
                   1941:     struct rtmsg rtmes;
                   1942:     int s, nb, wb;
                   1943:     char *cp;
                   1944:     const char *cmdstr = (cmd == RTM_ADD ? "Add" : "Delete");
                   1945:     struct sockaddr_storage sadst, samask, sagw;
                   1946:     char buf[48], buf1[48];
                   1947: 
                   1948:     s = socket(PF_ROUTE, SOCK_RAW, 0);
                   1949:     if (s < 0) {
                   1950:        Perror("[%s] IFACE: Can't get route socket", b->name);
                   1951:        return (-1);
                   1952:     }
                   1953:     memset(&rtmes, '\0', sizeof(rtmes));
                   1954:     rtmes.m_rtm.rtm_version = RTM_VERSION;
                   1955:     rtmes.m_rtm.rtm_type = cmd;
                   1956:     rtmes.m_rtm.rtm_addrs = RTA_DST;
                   1957:     rtmes.m_rtm.rtm_seq = ++gRouteSeq;
                   1958:     rtmes.m_rtm.rtm_pid = gPid;
                   1959:     rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
                   1960: 
                   1961:     u_rangetosockaddrs(dst, &sadst, &samask);
                   1962: #if defined(__KAME__) && !defined(NOINET6)
                   1963:     add_scope((struct sockaddr *)&sadst, b->iface.ifindex);
                   1964: #endif
                   1965: 
                   1966:     cp = rtmes.m_space;
                   1967:     cp += memcpy_roundup(cp, &sadst, sadst.ss_len);
                   1968:     if (gw != NULL) {
                   1969:        u_addrtosockaddr(gw, 0, &sagw);
                   1970: #if defined(__KAME__) && !defined(NOINET6)
                   1971:        add_scope((struct sockaddr *)&sagw, b->iface.ifindex);
                   1972: #endif
                   1973:        cp += memcpy_roundup(cp, &sagw, sagw.ss_len);
                   1974:        rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
                   1975:     } else if (cmd == RTM_ADD) {
                   1976:        Log(LG_ERR, ("[%s] IfaceSetRoute: gw is not set\n", b->name));
                   1977:        close(s);
                   1978:        return (-1);
                   1979:     }
                   1980: 
                   1981:     if (u_rangehost(dst)) {
                   1982:        rtmes.m_rtm.rtm_flags |= RTF_HOST;
                   1983:     } else {
                   1984:        cp += memcpy_roundup(cp, &samask, samask.ss_len);
                   1985:        rtmes.m_rtm.rtm_addrs |= RTA_NETMASK;
                   1986:     }
                   1987: 
                   1988:     nb = cp - (char *)&rtmes;
                   1989:     rtmes.m_rtm.rtm_msglen = nb;
                   1990:     wb = write(s, &rtmes, nb);
                   1991:     if (wb < 0) {
                   1992:        Log(LG_ERR, ("[%s] IFACE: %s route %s %s failed: %s",
                   1993:            b->name, cmdstr, u_rangetoa(dst, buf, sizeof(buf)), 
                   1994:            ((gw != NULL)?u_addrtoa(gw, buf1, sizeof(buf1)):""),
                   1995:            (rtmes.m_rtm.rtm_errno != 0)?strerror(rtmes.m_rtm.rtm_errno):strerror(errno)));
                   1996:        close(s);
                   1997:        return (-1);
                   1998:     }
                   1999:     close(s);
                   2000:     Log(LG_IFACE2, ("[%s] IFACE: %s route %s %s",
                   2001:            b->name, cmdstr, u_rangetoa(dst, buf, sizeof(buf)), 
                   2002:            ((gw != NULL)?u_addrtoa(gw, buf1, sizeof(buf1)):"")));
                   2003:     return (0);
                   2004: }
                   2005: 
                   2006: #ifndef USE_NG_TCPMSS
                   2007: void
                   2008: IfaceCorrectMSS(Mbuf pkt, uint16_t maxmss)
                   2009: {
                   2010:   struct ip    *iphdr;
                   2011:   struct tcphdr        *tc;
                   2012:   int          pktlen, hlen, olen, optlen, accumulate;
                   2013:   uint16_t     *mss;
                   2014:   u_char       *opt;
                   2015: 
                   2016:   if (pkt == NULL)
                   2017:     return;
                   2018: 
                   2019:   iphdr = (struct ip *)MBDATAU(pkt);
                   2020:   hlen = iphdr->ip_hl << 2;
                   2021:   pktlen = MBLEN(pkt) - hlen;
                   2022:   tc = (struct tcphdr *)(MBDATAU(pkt) + hlen);
                   2023:   hlen = tc->th_off << 2;
                   2024: 
                   2025:   /* Invalid header length or header without options. */
                   2026:   if (hlen <= sizeof(struct tcphdr) || hlen > pktlen)
                   2027:     return;
                   2028: 
                   2029:   /* MSS option only allowed within SYN packets. */  
                   2030:   if (!(tc->th_flags & TH_SYN))
                   2031:     return;
                   2032: 
                   2033:   for (olen = hlen - sizeof(struct tcphdr), opt = (u_char *)(tc + 1);
                   2034:        olen > 0; olen -= optlen, opt += optlen) {
                   2035:     if (*opt == TCPOPT_EOL)
                   2036:       break;
                   2037:     else if (*opt == TCPOPT_NOP)
                   2038:       optlen = 1;
                   2039:     else {
                   2040:       optlen = *(opt + 1);
                   2041:       if (optlen <= 0 || optlen > olen)
                   2042:        break;
                   2043:       if (*opt == TCPOPT_MAXSEG) {
                   2044:        if (optlen != TCPOLEN_MAXSEG)
                   2045:          continue;
                   2046:        mss = (u_int16_t *)(opt + 2);
                   2047:        if (ntohs(*mss) > maxmss) {
                   2048:          accumulate = *mss;
                   2049:          *mss = htons(maxmss);
                   2050:          accumulate -= *mss;
                   2051:          ADJUST_CHECKSUM(accumulate, tc->th_sum);
                   2052:        }
                   2053:       }
                   2054:     }
                   2055:   }
                   2056: }
                   2057: #endif
                   2058: 
                   2059: static int
                   2060: IfaceNgIpInit(Bund b, int ready)
                   2061: {
                   2062:     struct ngm_connect cn;
                   2063:     char               path[NG_PATHSIZ];
                   2064:     char               hook[NG_HOOKSIZ];
                   2065: 
                   2066:     if (!ready) {
                   2067:        /* Dial-on-Demand mode */
                   2068:        /* Use demand hook of the socket node */
                   2069:        snprintf(path, sizeof(path), ".:");
                   2070:        snprintf(hook, sizeof(hook), "4%d", b->id);
                   2071: 
                   2072:     } else {
                   2073: 
                   2074:        snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                   2075:        strcpy(hook, NG_PPP_HOOK_INET);
                   2076: 
                   2077: #ifdef USE_NG_NAT
                   2078:        /* Add a nat node if configured */
                   2079:        if (Enabled(&b->iface.options, IFACE_CONF_NAT)) {
                   2080:            if (IfaceInitNAT(b, path, hook))
                   2081:                goto fail;
                   2082:            b->iface.nat_up = 1;
                   2083:        }
                   2084: #endif
                   2085: 
                   2086:        /* Add a tee node if configured */
                   2087:        if (Enabled(&b->iface.options, IFACE_CONF_TEE)) {
                   2088:            if (IfaceInitTee(b, path, hook, 0))
                   2089:                goto fail;
                   2090:            b->iface.tee_up = 1;
                   2091:        }
                   2092:   
                   2093: #ifdef USE_NG_IPACCT
                   2094:        /* Connect a ipacct node if configured */
                   2095:        if (Enabled(&b->iface.options, IFACE_CONF_IPACCT)) {
                   2096:            if (IfaceInitIpacct(b, path, hook))
                   2097:                goto fail;
                   2098:            b->iface.ipacct_up = 1;
                   2099:        }
                   2100: #endif /* USE_NG_IPACCT */
                   2101: 
                   2102: #ifdef USE_NG_NETFLOW
                   2103: #ifdef NG_NETFLOW_CONF_INGRESS
                   2104:        /* Connect a netflow node if configured */
                   2105:        if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN) ||
                   2106:            Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) {
                   2107:            if (IfaceInitNetflow(b, path, hook, 
                   2108:                Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)?1:0,
                   2109:                Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)?1:0))
                   2110:                goto fail;
                   2111:            if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN))
                   2112:                b->iface.nfin_up = 1;
                   2113:            if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT))
                   2114:                b->iface.nfout_up = 1;
                   2115:        }
                   2116: #else  /* NG_NETFLOW_CONF_INGRESS */
                   2117:        /* Connect a netflow node if configured */
                   2118:        if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)) {
                   2119:            if (IfaceInitNetflow(b, path, hook, 1, 0))
                   2120:                goto fail;
                   2121:            b->iface.nfin_up = 1;
                   2122:        }
                   2123: 
                   2124:        if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) {
                   2125:            if (IfaceInitNetflow(b, path, hook, 0, 1))
                   2126:                goto fail;
                   2127:            b->iface.nfout_up = 1;
                   2128:        }
                   2129: #endif /* NG_NETFLOW_CONF_INGRESS */
                   2130: #endif /* USE_NG_NETFLOW */
                   2131: 
                   2132:     }
                   2133: 
                   2134: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
                   2135:     if (Enabled(&b->iface.options, IFACE_CONF_TCPMSSFIX)) {
                   2136:        if (IfaceInitMSS(b, path, hook))
                   2137:            goto fail;
                   2138:        b->iface.mss_up = 1;
                   2139:     }
                   2140: #endif
                   2141: 
                   2142: #ifdef USE_NG_BPF
                   2143:     if (IfaceInitLimits(b, path, hook))
                   2144:        goto fail;
                   2145: #endif
                   2146: 
                   2147:     /* Connect graph to the iface node. */
                   2148:     memset(&cn, 0, sizeof(cn));
                   2149:     strcpy(cn.ourhook, hook);
                   2150:     snprintf(cn.path, sizeof(cn.path), "%s:", b->iface.ngname);
                   2151:     strcpy(cn.peerhook, NG_IFACE_HOOK_INET);
                   2152:     if (NgSendMsg(gLinksCsock, path,
                   2153:            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                   2154:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   2155:            b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   2156:        goto fail;
                   2157:     }
                   2158: 
                   2159:     if (ready) {
                   2160: #ifdef USE_NG_NETFLOW
                   2161: #ifdef NG_NETFLOW_CONF_INGRESS
                   2162:        if (b->iface.nfin_up || b->iface.nfout_up)
                   2163:            IfaceSetupNetflow(b, b->iface.nfin_up, b->iface.nfout_up);
                   2164: #else /* NG_NETFLOW_CONF_INGRESS */
                   2165:        if (b->iface.nfin_up)
                   2166:            IfaceSetupNetflow(b, 1, 0);
                   2167: 
                   2168:        if (b->iface.nfout_up)
                   2169:            IfaceSetupNetflow(b, 0, 1);
                   2170: #endif /* NG_NETFLOW_CONF_INGRESS */
                   2171: #endif /* USE_NG_NETFLOW */
                   2172:     }
                   2173: 
                   2174: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
                   2175:     if (b->iface.mss_up)
                   2176:         IfaceSetupMSS(b, MAXMSS(b->iface.mtu));
                   2177: #endif
                   2178:     
                   2179: #ifdef USE_NG_BPF
                   2180:     IfaceSetupLimits(b);
                   2181: #endif
                   2182: 
                   2183:     /* OK */
                   2184:     return(0);
                   2185: 
                   2186: fail:
                   2187:     return(-1);
                   2188: }
                   2189: 
                   2190: /*
                   2191:  * IfaceNgIpShutdown()
                   2192:  */
                   2193: 
                   2194: static void
                   2195: IfaceNgIpShutdown(Bund b)
                   2196: {
                   2197:     char               path[NG_PATHSIZ];
                   2198: 
                   2199: #ifdef USE_NG_BPF
                   2200:     IfaceShutdownLimits(b); /* Limits must shutdown first to save final stats. */
                   2201: #endif
                   2202: #ifdef USE_NG_NAT
                   2203:     if (b->iface.nat_up)
                   2204:        IfaceShutdownNAT(b);
                   2205:     b->iface.nat_up = 0;
                   2206: #endif
                   2207:     if (b->iface.tee_up)
                   2208:        IfaceShutdownTee(b, 0);
                   2209:     b->iface.tee_up = 0;
                   2210: #ifdef USE_NG_NETFLOW
                   2211: #ifdef NG_NETFLOW_CONF_INGRESS
                   2212:     if (b->iface.nfin_up || b->iface.nfout_up)
                   2213:        IfaceShutdownNetflow(b, b->iface.nfin_up, b->iface.nfout_up);
                   2214:     b->iface.nfin_up = 0;
                   2215:     b->iface.nfout_up = 0;
                   2216: #else /* NG_NETFLOW_CONF_INGRESS */
                   2217:     if (b->iface.nfin_up)
                   2218:        IfaceShutdownNetflow(b, 1, 0);
                   2219:     b->iface.nfin_up = 0;
                   2220:     if (b->iface.nfout_up)
                   2221:        IfaceShutdownNetflow(b, 0, 1);
                   2222:     b->iface.nfout_up = 0;
                   2223: #endif /* NG_NETFLOW_CONF_INGRESS */
                   2224: #endif
                   2225: #ifdef USE_NG_IPACCT
                   2226:     if (b->iface.ipacct_up)
                   2227:        IfaceShutdownIpacct(b);
                   2228:     b->iface.ipacct_up = 0;
                   2229: #endif
                   2230: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
                   2231:     if (b->iface.mss_up)
                   2232:        IfaceShutdownMSS(b);
                   2233: #endif
                   2234:     b->iface.mss_up = 0;
                   2235: 
                   2236:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                   2237:     NgFuncDisconnect(gLinksCsock, b->name, path, NG_PPP_HOOK_INET);
                   2238: 
                   2239:     snprintf(path, sizeof(path), "%s:", b->iface.ngname);
                   2240:     NgFuncDisconnect(gLinksCsock, b->name, path, NG_IFACE_HOOK_INET);
                   2241: }
                   2242: 
                   2243: static int
                   2244: IfaceNgIpv6Init(Bund b, int ready)
                   2245: {
                   2246:     struct ngm_connect cn;
                   2247:     char               path[NG_PATHSIZ];
                   2248:     char               hook[NG_HOOKSIZ];
                   2249: 
                   2250:     if (!ready) {
                   2251:        /* Dial-on-Demand mode */
                   2252:        /* Use demand hook of the socket node */
                   2253:        snprintf(path, sizeof(path), ".:");
                   2254:        snprintf(hook, sizeof(hook), "6%d", b->id);
                   2255:     } else {
                   2256:        snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                   2257:        strcpy(hook, NG_PPP_HOOK_IPV6);
                   2258: 
                   2259:        /* Add a tee node if configured */
                   2260:        if (Enabled(&b->iface.options, IFACE_CONF_TEE)) {
                   2261:            if (IfaceInitTee(b, path, hook, 1))
                   2262:                goto fail;
                   2263:            b->iface.tee6_up = 1;
                   2264:        }
                   2265:   
                   2266:     }
                   2267: 
                   2268:     /* Connect graph to the iface node. */
                   2269:     strcpy(cn.ourhook, hook);
                   2270:     snprintf(cn.path, sizeof(cn.path), "%s:", b->iface.ngname);
                   2271:     strcpy(cn.peerhook, NG_IFACE_HOOK_INET6);
                   2272:     if (NgSendMsg(gLinksCsock, path,
                   2273:            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                   2274:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   2275:            b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   2276:        goto fail;
                   2277:     }
                   2278: 
                   2279:     /* OK */
                   2280:     return(0);
                   2281: 
                   2282: fail:
                   2283:     return(-1);
                   2284: }
                   2285: 
                   2286: /*
                   2287:  * IfaceNgIpv6Shutdown()
                   2288:  */
                   2289: 
                   2290: static void
                   2291: IfaceNgIpv6Shutdown(Bund b)
                   2292: {
                   2293:     char               path[NG_PATHSIZ];
                   2294: 
                   2295:     if (b->iface.tee6_up)
                   2296:        IfaceShutdownTee(b, 1);
                   2297:     b->iface.tee6_up = 0;
                   2298: 
                   2299:     snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                   2300:     NgFuncDisconnect(gLinksCsock, b->name, path, NG_PPP_HOOK_IPV6);
                   2301: 
                   2302:     snprintf(path, sizeof(path), "%s:", b->iface.ngname);
                   2303:     NgFuncDisconnect(gLinksCsock, b->name, path, NG_IFACE_HOOK_INET6);
                   2304: }
                   2305: 
                   2306: #ifdef USE_NG_NAT
                   2307: static int
                   2308: IfaceInitNAT(Bund b, char *path, char *hook)
                   2309: {
                   2310:     NatState      const nat = &b->iface.nat;
                   2311:     struct ngm_mkpeer  mp;
                   2312:     struct ngm_name    nm;
                   2313:     struct in_addr     ip;
                   2314: #ifdef NG_NAT_LOG
                   2315:     struct ng_nat_mode mode;
                   2316: #endif  
                   2317:     Log(LG_IFACE2, ("[%s] IFACE: Connecting NAT", b->name));
                   2318:   
                   2319:     strcpy(mp.type, NG_NAT_NODE_TYPE);
                   2320:     strcpy(mp.ourhook, hook);
                   2321:     strcpy(mp.peerhook, NG_NAT_HOOK_IN);
                   2322:     if (NgSendMsg(gLinksCsock, path,
                   2323:        NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   2324:       Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
                   2325:        b->name, NG_NAT_NODE_TYPE, path, mp.ourhook);
                   2326:       return(-1);
                   2327:     }
                   2328:     strlcat(path, ".", NG_PATHSIZ);
                   2329:     strlcat(path, hook, NG_PATHSIZ);
                   2330:     snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-nat", gPid, b->name);
                   2331:     if (NgSendMsg(gLinksCsock, path,
                   2332:        NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   2333:       Perror("[%s] can't name %s node", b->name, NG_NAT_NODE_TYPE);
                   2334:       return(-1);
                   2335:     }
                   2336:     strcpy(hook, NG_NAT_HOOK_OUT);
                   2337: 
                   2338:     /* Set NAT IP */
                   2339:     if (u_addrempty(&nat->alias_addr)) {
                   2340:        ip.s_addr = 1; // Set something just to make it ready
                   2341:     } else {
                   2342:        ip = nat->alias_addr.u.ip4;
                   2343:     }
                   2344:     if (NgSendMsg(gLinksCsock, path,
                   2345:            NGM_NAT_COOKIE, NGM_NAT_SET_IPADDR, &ip, sizeof(ip)) < 0)
                   2346:        Perror("[%s] can't set NAT ip", b->name);
                   2347: 
                   2348: #ifdef NG_NAT_LOG
                   2349:     /* Set NAT mode */
                   2350:     mode.flags = 0;
                   2351:     if (Enabled(&nat->options, NAT_CONF_LOG))
                   2352:        mode.flags |= NG_NAT_LOG;
                   2353:     if (!Enabled(&nat->options, NAT_CONF_INCOMING))
                   2354:        mode.flags |= NG_NAT_DENY_INCOMING;
                   2355:     if (Enabled(&nat->options, NAT_CONF_SAME_PORTS))
                   2356:        mode.flags |= NG_NAT_SAME_PORTS;
                   2357:     if (Enabled(&nat->options, NAT_CONF_UNREG_ONLY))
                   2358:        mode.flags |= NG_NAT_UNREGISTERED_ONLY;
                   2359:     
                   2360:     mode.mask = NG_NAT_LOG | NG_NAT_DENY_INCOMING | 
                   2361:        NG_NAT_SAME_PORTS | NG_NAT_UNREGISTERED_ONLY;
                   2362:     if (NgSendMsg(gLinksCsock, path,
                   2363:            NGM_NAT_COOKIE, NGM_NAT_SET_MODE, &mode, sizeof(mode)) < 0)
                   2364:        Perror("[%s] can't set NAT mode", b->name);
                   2365: 
                   2366:     /* Set NAT target IP */
                   2367:     if (!u_addrempty(&nat->target_addr)) {
                   2368:        ip = nat->target_addr.u.ip4;
                   2369:        if (NgSendMsg(gLinksCsock, path,
                   2370:                NGM_NAT_COOKIE, NGM_NAT_SET_IPADDR, &ip, sizeof(ip)) < 0) {
                   2371:            Perror("[%s] can't set NAT target IP", b->name);
                   2372:        }
                   2373:     }
                   2374: #endif
                   2375: 
                   2376:     return(0);
                   2377: }
                   2378: 
                   2379: static int
                   2380: IfaceSetupNAT(Bund b)
                   2381: {
                   2382:     NatState   const nat = &b->iface.nat;
                   2383:     char       path[NG_PATHSIZ];
                   2384:     int k;
                   2385: 
                   2386:     if (u_addrempty(&nat->alias_addr)) {
                   2387:        snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, b->name);
                   2388:        if (NgSendMsg(gLinksCsock, path,
                   2389:                NGM_NAT_COOKIE, NGM_NAT_SET_IPADDR,
                   2390:                &b->iface.self_addr.addr.u.ip4,
                   2391:                sizeof(b->iface.self_addr.addr.u.ip4)) < 0) {
                   2392:            Perror("[%s] can't set NAT ip", b->name);
                   2393:            return (-1);
                   2394:        }
                   2395:     }
                   2396: #ifdef NG_NAT_DESC_LENGTH
                   2397:     /* redirect-port */
                   2398:     for(k = 0; k < NM_PORT; k++) {
                   2399:       if(nat->nrpt_id[k]) {
                   2400:        if (NgSendMsg(gLinksCsock, path,
                   2401:                NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PORT, &nat->nrpt[k],
                   2402:                sizeof(struct ng_nat_redirect_port)) < 0) {
                   2403:            Perror("[%s] can't set NAT redirect-port", b->name);
                   2404:        }
                   2405:       }
                   2406:     }
                   2407:     /* redirect-addr */
                   2408:     for(k = 0; k < NM_ADDR; k++) {
                   2409:       if(nat->nrad_id[k]) {
                   2410:        if (NgSendMsg(gLinksCsock, path,
                   2411:                NGM_NAT_COOKIE, NGM_NAT_REDIRECT_ADDR, &nat->nrad[k],
                   2412:                sizeof(struct ng_nat_redirect_addr)) < 0) {
                   2413:            Perror("[%s] can't set NAT redirect-addr", b->name);
                   2414:        }
                   2415:       }
                   2416:     }
                   2417:     /* redirect-proto */
                   2418:     for(k = 0; k < NM_PROTO; k++) {
                   2419:       if(nat->nrpr_id[k]) {
                   2420:        if (NgSendMsg(gLinksCsock, path,
                   2421:                NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PROTO, &nat->nrpr[k],
                   2422:                sizeof(struct ng_nat_redirect_proto)) < 0) {
                   2423:            Perror("[%s] can't set NAT redirect-proto", b->name);
                   2424:        }
                   2425:       }
                   2426:     }
                   2427: #endif
                   2428:     return (0);
                   2429: }
                   2430: 
                   2431: static void
                   2432: IfaceShutdownNAT(Bund b)
                   2433: {
                   2434:     char       path[NG_PATHSIZ];
                   2435: 
                   2436:     snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, b->name);
                   2437:     NgFuncShutdownNode(gLinksCsock, b->name, path);
                   2438: }
                   2439: #endif /* USE_NG_NAT */
                   2440: 
                   2441: static int
                   2442: IfaceInitTee(Bund b, char *path, char *hook, int v6)
                   2443: {
                   2444:     struct ngm_mkpeer  mp;
                   2445:     struct ngm_name    nm;
                   2446: 
                   2447:     Log(LG_IFACE2, ("[%s] IFACE: Connecting tee%s", b->name, v6?"6":""));
                   2448:   
                   2449:     strcpy(mp.type, NG_TEE_NODE_TYPE);
                   2450:     strcpy(mp.ourhook, hook);
                   2451:     strcpy(mp.peerhook, NG_TEE_HOOK_RIGHT);
                   2452:     if (NgSendMsg(gLinksCsock, path,
                   2453:        NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   2454:       Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
                   2455:        b->name, NG_TEE_NODE_TYPE, path, mp.ourhook);
                   2456:       return(-1);
                   2457:     }
                   2458:     strlcat(path, ".", NG_PATHSIZ);
                   2459:     strlcat(path, hook, NG_PATHSIZ);
                   2460:     snprintf(nm.name, sizeof(nm.name), "%s-tee%s", b->iface.ifname, v6?"6":"");
                   2461:     if (NgSendMsg(gLinksCsock, path,
                   2462:        NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   2463:       Perror("[%s] can't name %s node", b->name, NG_TEE_NODE_TYPE);
                   2464:       return(-1);
                   2465:     }
                   2466:     strcpy(hook, NG_TEE_HOOK_LEFT);
                   2467: 
                   2468:     return(0);
                   2469: }
                   2470: 
                   2471: static void
                   2472: IfaceShutdownTee(Bund b, int v6)
                   2473: {
                   2474:     char       path[NG_PATHSIZ];
                   2475: 
                   2476:     snprintf(path, sizeof(path), "%s-tee%s:", b->iface.ifname, v6?"6":"");
                   2477:     NgFuncShutdownNode(gLinksCsock, b->name, path);
                   2478: }
                   2479: 
                   2480: #ifdef USE_NG_IPACCT
                   2481: static int
                   2482: IfaceInitIpacct(Bund b, char *path, char *hook)
                   2483: {
                   2484:     struct ngm_mkpeer  mp;
                   2485:     struct ngm_name    nm;
                   2486:     struct ngm_connect  cn;
                   2487:     char               path1[NG_PATHSIZ];
                   2488:     struct {
                   2489:        struct ng_ipacct_mesg m;
                   2490:        int             data;
                   2491:     } ipam;
                   2492: 
                   2493:     Log(LG_IFACE2, ("[%s] IFACE: Connecting ipacct", b->name));
                   2494:   
                   2495:     strcpy(mp.type, NG_TEE_NODE_TYPE);
                   2496:     strcpy(mp.ourhook, hook);
                   2497:     strcpy(mp.peerhook, NG_TEE_HOOK_RIGHT);
                   2498:     if (NgSendMsg(gLinksCsock, path,
                   2499:        NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   2500:       Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
                   2501:        b->name, NG_TEE_NODE_TYPE, path, mp.ourhook);
                   2502:       return(-1);
                   2503:     }
                   2504:     strlcat(path, ".", NG_PATHSIZ);
                   2505:     strlcat(path, hook, NG_PATHSIZ);
                   2506:     snprintf(nm.name, sizeof(nm.name), "%s_acct_tee", b->iface.ifname);
                   2507:     if (NgSendMsg(gLinksCsock, path,
                   2508:        NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   2509:       Perror("[%s] can't name %s node", b->name, NG_TEE_NODE_TYPE);
                   2510:       return(-1);
                   2511:     }
                   2512:     strcpy(hook, NG_TEE_HOOK_LEFT);
                   2513: 
                   2514:     strcpy(mp.type, NG_IPACCT_NODE_TYPE);
                   2515:     strcpy(mp.ourhook, NG_TEE_HOOK_RIGHT2LEFT);
                   2516:     snprintf(mp.peerhook, sizeof(mp.peerhook), "%s_in", b->iface.ifname);
                   2517:     if (NgSendMsg(gLinksCsock, path,
                   2518:        NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   2519:       Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
                   2520:        b->name, NG_IPACCT_NODE_TYPE, path, mp.ourhook);
                   2521:       return(-1);
                   2522:     }
                   2523:     snprintf(path1, sizeof(path1), "%s.%s", path, NG_TEE_HOOK_RIGHT2LEFT);
                   2524:     snprintf(nm.name, sizeof(nm.name), "%s_ip_acct", b->iface.ifname);
                   2525:     if (NgSendMsg(gLinksCsock, path1,
                   2526:        NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   2527:       Perror("[%s] can't name %s node", b->name, NG_IPACCT_NODE_TYPE);
                   2528:       return(-1);
                   2529:     }
                   2530:     strcpy(cn.ourhook, NG_TEE_HOOK_LEFT2RIGHT);
                   2531:     strcpy(cn.path, NG_TEE_HOOK_RIGHT2LEFT);
                   2532:     snprintf(cn.peerhook, sizeof(cn.peerhook), "%s_out", b->iface.ifname);
                   2533:     if (NgSendMsg(gLinksCsock, path, NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
                   2534:        sizeof(cn)) < 0) {
                   2535:       Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   2536:         b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   2537:       return (-1);
                   2538:     }
                   2539:     
                   2540:     snprintf(ipam.m.hname, sizeof(ipam.m.hname), "%s_in", b->iface.ifname);
                   2541:     ipam.data = DLT_RAW;
                   2542:     if (NgSendMsg(gLinksCsock, path1, NGM_IPACCT_COOKIE, NGM_IPACCT_SETDLT, 
                   2543:        &ipam, sizeof(ipam)) < 0) {
                   2544:       Perror("[%s] can't set DLT \"%s\"->\"%s\"", b->name, path, ipam.m.hname);
                   2545:       return (-1);
                   2546:     }
                   2547:     ipam.data = 10000;
                   2548:     if (NgSendMsg(gLinksCsock, path1, NGM_IPACCT_COOKIE, NGM_IPACCT_STHRS, 
                   2549:        &ipam, sizeof(ipam)) < 0) {
                   2550:       Perror("[%s] can't set DLT \"%s\"->\"%s\"", b->name, path, ipam.m.hname);
                   2551:       return (-1);
                   2552:     }
                   2553:     
                   2554:     snprintf(ipam.m.hname, sizeof(ipam.m.hname), "%s_out", b->iface.ifname);
                   2555:     ipam.data = DLT_RAW;
                   2556:     if (NgSendMsg(gLinksCsock, path1, NGM_IPACCT_COOKIE, NGM_IPACCT_SETDLT, 
                   2557:        &ipam, sizeof(ipam)) < 0) {
                   2558:       Perror("[%s] can't set DLT \"%s\"->\"%s\"", b->name, path, ipam.m.hname);
                   2559:       return (-1);
                   2560:     }
                   2561:     ipam.data = 10000;
                   2562:     if (NgSendMsg(gLinksCsock, path1, NGM_IPACCT_COOKIE, NGM_IPACCT_STHRS, 
                   2563:        &ipam, sizeof(ipam)) < 0) {
                   2564:       Perror("[%s] can't set DLT \"%s\"->\"%s\"", b->name, path, ipam.m.hname);
                   2565:       return (-1);
                   2566:     }
                   2567: 
                   2568:     return(0);
                   2569: }
                   2570: 
                   2571: static void
                   2572: IfaceShutdownIpacct(Bund b)
                   2573: {
                   2574:     char       path[NG_PATHSIZ];
                   2575: 
                   2576:     snprintf(path, sizeof(path), "%s_acct_tee:", b->iface.ifname);
                   2577:     NgFuncShutdownNode(gLinksCsock, b->name, path);
                   2578: }
                   2579: #endif
                   2580: 
                   2581: #ifdef USE_NG_NETFLOW
                   2582: static int
                   2583: IfaceInitNetflow(Bund b, char *path, char *hook, char in, char out)
                   2584: {
                   2585:     struct ngm_connect cn;
                   2586:     int nif;
                   2587: 
                   2588: #ifdef NG_NETFLOW_CONF_INGRESS
                   2589:     nif = gNetflowIface + b->id;
                   2590: #else
                   2591:     nif = gNetflowIface + b->id*2 + out;
                   2592: #endif
                   2593: 
                   2594:     Log(LG_IFACE2, ("[%s] IFACE: Connecting netflow (%s)", b->name, out?"out":"in"));
                   2595:   
                   2596:     /* Create global ng_netflow(4) node if not yet. */
                   2597:     if (gNetflowNodeID == 0) {
                   2598:        if (NgFuncInitGlobalNetflow())
                   2599:            return(-1);
                   2600:     }
                   2601: 
                   2602:     /* Connect ng_netflow(4) node to the ng_bpf(4)/ng_tee(4) node. */
                   2603:     strcpy(cn.ourhook, hook);
                   2604:     snprintf(cn.path, sizeof(cn.path), "[%x]:", gNetflowNodeID);
                   2605: #ifndef NG_NETFLOW_CONF_INGRESS
                   2606:     if (out) {
                   2607:        snprintf(cn.peerhook, sizeof(cn.peerhook), "%s%d", NG_NETFLOW_HOOK_OUT,
                   2608:            nif);
                   2609:     } else {
                   2610: #endif
                   2611:        snprintf(cn.peerhook, sizeof(cn.peerhook), "%s%d", NG_NETFLOW_HOOK_DATA,
                   2612:            nif);
                   2613: #ifndef NG_NETFLOW_CONF_INGRESS
                   2614:     }
                   2615: #endif
                   2616:     if (NgSendMsg(gLinksCsock, path, NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
                   2617:        sizeof(cn)) < 0) {
                   2618:       Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   2619:         b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   2620:       return (-1);
                   2621:     }
                   2622:     strlcat(path, ".", NG_PATHSIZ);
                   2623:     strlcat(path, hook, NG_PATHSIZ);
                   2624: #ifndef NG_NETFLOW_CONF_INGRESS
                   2625:     if (out) {
                   2626:        snprintf(hook, NG_HOOKSIZ, "%s%d", NG_NETFLOW_HOOK_DATA, nif);
                   2627:     } else {
                   2628: #endif
                   2629:        snprintf(hook, NG_HOOKSIZ, "%s%d", NG_NETFLOW_HOOK_OUT, nif);
                   2630: #ifndef NG_NETFLOW_CONF_INGRESS
                   2631:     }
                   2632: #endif
                   2633:     return (0);
                   2634: }
                   2635: 
                   2636: static int
                   2637: IfaceSetupNetflow(Bund b, char in, char out)
                   2638: {
                   2639:     char path[NG_PATHSIZ];
                   2640:     struct ng_netflow_setdlt    nf_setdlt;
                   2641:     struct ng_netflow_setifindex nf_setidx;
                   2642: #ifdef NG_NETFLOW_CONF_INGRESS
                   2643:     struct ng_netflow_setconfig  nf_setconf;
                   2644: #endif
                   2645:     int nif;
                   2646: 
                   2647: #ifdef NG_NETFLOW_CONF_INGRESS
                   2648:     nif = gNetflowIface + b->id;
                   2649: #else
                   2650:     nif = gNetflowIface + b->id*2 + out;
                   2651: #endif
                   2652:     
                   2653:     /* Configure data link type and interface index. */
                   2654:     snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
                   2655:     nf_setdlt.iface = nif;
                   2656:     nf_setdlt.dlt = DLT_RAW;
                   2657:     if (NgSendMsg(gLinksCsock, path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_SETDLT,
                   2658:        &nf_setdlt, sizeof(nf_setdlt)) < 0) {
                   2659:       Perror("[%s] can't configure data link type on %s", b->name, path);
                   2660:       goto fail;
                   2661:     }
                   2662: #ifdef NG_NETFLOW_CONF_INGRESS
                   2663:     nf_setconf.iface = nif;
                   2664:     nf_setconf.conf = 
                   2665:        (in?NG_NETFLOW_CONF_INGRESS:0) |
                   2666:        (out?NG_NETFLOW_CONF_EGRESS:0) |
                   2667:        (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_ONCE)?NG_NETFLOW_CONF_ONCE:0);
                   2668:     if (NgSendMsg(gLinksCsock, path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_SETCONFIG,
                   2669:        &nf_setconf, sizeof(nf_setconf)) < 0) {
                   2670:       Perror("[%s] can't set config on %s", b->name, path);
                   2671:       goto fail;
                   2672:     }
                   2673: #endif
                   2674: #ifndef NG_NETFLOW_CONF_INGRESS
                   2675:     if (!out) {
                   2676: #endif
                   2677:        nf_setidx.iface = nif;
                   2678:        nf_setidx.index = if_nametoindex(b->iface.ifname);
                   2679:        if (NgSendMsg(gLinksCsock, path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_SETIFINDEX,
                   2680:            &nf_setidx, sizeof(nf_setidx)) < 0) {
                   2681:          Perror("[%s] can't configure interface index on %s", b->name, path);
                   2682:          goto fail;
                   2683:        }
                   2684: #ifndef NG_NETFLOW_CONF_INGRESS
                   2685:     }
                   2686: #endif
                   2687: 
                   2688:     return 0;
                   2689: fail:
                   2690:     return -1;
                   2691: }
                   2692: 
                   2693: static void
                   2694: IfaceShutdownNetflow(Bund b, char in, char out)
                   2695: {
                   2696:     char       path[NG_PATHSIZ];
                   2697:     char       hook[NG_HOOKSIZ];
                   2698:     int nif;
                   2699: 
                   2700: #ifdef NG_NETFLOW_CONF_INGRESS
                   2701:     nif = gNetflowIface + b->id;
                   2702: #else
                   2703:     nif = gNetflowIface + b->id*2 + out;
                   2704: #endif
                   2705: 
                   2706:     snprintf(path, NG_PATHSIZ, "[%x]:", gNetflowNodeID);
                   2707:     snprintf(hook, NG_HOOKSIZ, "%s%d", NG_NETFLOW_HOOK_DATA, nif);
                   2708:     NgFuncDisconnect(gLinksCsock, b->name, path, hook);
                   2709:     snprintf(hook, NG_HOOKSIZ, "%s%d", NG_NETFLOW_HOOK_OUT, nif);
                   2710:     NgFuncDisconnect(gLinksCsock, b->name, path, hook);
                   2711: }
                   2712: #endif
                   2713: 
                   2714: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
                   2715: static int
                   2716: IfaceInitMSS(Bund b, char *path, char *hook)
                   2717: {
                   2718:        struct ngm_mkpeer       mp;
                   2719:        struct ngm_name         nm;
                   2720: #ifndef USE_NG_TCPMSS
                   2721:        struct ngm_connect      cn;
                   2722: #endif
                   2723: 
                   2724:        Log(LG_IFACE2, ("[%s] IFACE: Connecting tcpmssfix", b->name));
                   2725:   
                   2726: #ifdef USE_NG_TCPMSS
                   2727:        /* Create ng_tcpmss(4) node. */
                   2728:        strcpy(mp.type, NG_TCPMSS_NODE_TYPE);
                   2729:        strlcpy(mp.ourhook, hook, sizeof(mp.ourhook));
                   2730:        strcpy(mp.peerhook, "in");
                   2731:        if (NgSendMsg(gLinksCsock, path,
                   2732:                NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   2733:            Perror("can't create %s node at \"%s\"->\"%s\"",
                   2734:                NG_TCPMSS_NODE_TYPE, path, mp.ourhook);
                   2735:            goto fail;
                   2736:        }
                   2737: 
                   2738:        strlcat(path, ".", NG_PATHSIZ);
                   2739:        strlcat(path, hook, NG_PATHSIZ);
                   2740:        snprintf(hook, NG_HOOKSIZ, "out");
                   2741: 
                   2742:        /* Set the new node's name. */
                   2743:        snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-mss", gPid, b->name);
                   2744:        if (NgSendMsg(gLinksCsock, path,
                   2745:                NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   2746:            Perror("can't name %s node", NG_TCPMSS_NODE_TYPE);
                   2747:            goto fail;
                   2748:        }
                   2749: 
                   2750: #else
                   2751:     /* Create a bpf node for SYN detection. */
                   2752:     strcpy(mp.type, NG_BPF_NODE_TYPE);
                   2753:     strlcpy(mp.ourhook, hook, sizeof(mp.ourhook));
                   2754:     strcpy(mp.peerhook, "ppp");
                   2755:     if (NgSendMsg(gLinksCsock, path,
                   2756:            NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   2757:        Perror("can't create %s node at \"%s\"->\"%s\"",
                   2758:            NG_BPF_NODE_TYPE, path, mp.ourhook);
                   2759:        goto fail;
                   2760:     }
                   2761: 
                   2762:     strlcat(path, ".", NG_PATHSIZ);
                   2763:     strlcat(path, hook, NG_PATHSIZ);
                   2764:     strcpy(hook, "iface");
                   2765: 
                   2766:     /* Set the new node's name. */
                   2767:     snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-mss", gPid, b->name);
                   2768:     if (NgSendMsg(gLinksCsock, path,
                   2769:            NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   2770:        Perror("can't name tcpmssfix %s node", NG_BPF_NODE_TYPE);
                   2771:        goto fail;
                   2772:     }
                   2773: 
                   2774:     /* Connect to the bundle socket node. */
                   2775:     strlcpy(cn.path, path, sizeof(cn.path));
                   2776:     snprintf(cn.ourhook, sizeof(cn.ourhook), "i%d", b->id);
                   2777:     strcpy(cn.peerhook, MPD_HOOK_TCPMSS_IN);
                   2778:     if (NgSendMsg(gLinksCsock, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
                   2779:            sizeof(cn)) < 0) {
                   2780:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   2781:            b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   2782:        goto fail;
                   2783:     }
                   2784: 
                   2785:     strlcpy(cn.path, path, sizeof(cn.path));
                   2786:     snprintf(cn.ourhook, sizeof(cn.ourhook), "o%d", b->id);
                   2787:     strcpy(cn.peerhook, MPD_HOOK_TCPMSS_OUT);
                   2788:     if (NgSendMsg(gLinksCsock, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
                   2789:            sizeof(cn)) < 0) {
                   2790:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   2791:            b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   2792:        goto fail;
                   2793:     }
                   2794: #endif /* USE_NG_TCPMSS */
                   2795: 
                   2796:     return (0);
                   2797: fail:
                   2798:     return (-1);
                   2799: }
                   2800: 
                   2801: /*
                   2802:  * BundConfigMSS()
                   2803:  *
                   2804:  * Configure the tcpmss node to reduce MSS to given value.
                   2805:  */
                   2806: 
                   2807: static void
                   2808: IfaceSetupMSS(Bund b, uint16_t maxMSS)
                   2809: {
                   2810: #ifdef USE_NG_TCPMSS
                   2811:   struct       ng_tcpmss_config tcpmsscfg;
                   2812:   char         path[NG_PATHSIZ];
                   2813: 
                   2814:   snprintf(path, sizeof(path), "mpd%d-%s-mss:", gPid, b->name);
                   2815: 
                   2816:   /* Send configure message. */
                   2817:   memset(&tcpmsscfg, 0, sizeof(tcpmsscfg));
                   2818:   tcpmsscfg.maxMSS = maxMSS;
                   2819: 
                   2820:   snprintf(tcpmsscfg.inHook, sizeof(tcpmsscfg.inHook), "in");
                   2821:   snprintf(tcpmsscfg.outHook, sizeof(tcpmsscfg.outHook), "out");
                   2822:   if (NgSendMsg(gLinksCsock, path, NGM_TCPMSS_COOKIE, NGM_TCPMSS_CONFIG,
                   2823:       &tcpmsscfg, sizeof(tcpmsscfg)) < 0) {
                   2824:     Perror("[%s] can't configure %s node program", b->name, NG_TCPMSS_NODE_TYPE);
                   2825:   }
                   2826:   snprintf(tcpmsscfg.inHook, sizeof(tcpmsscfg.inHook), "out");
                   2827:   snprintf(tcpmsscfg.outHook, sizeof(tcpmsscfg.outHook), "in");
                   2828:   if (NgSendMsg(gLinksCsock, path, NGM_TCPMSS_COOKIE, NGM_TCPMSS_CONFIG,
                   2829:       &tcpmsscfg, sizeof(tcpmsscfg)) < 0) {
                   2830:     Perror("[%s] can't configure %s node program", b->name, NG_TCPMSS_NODE_TYPE);
                   2831:   }
                   2832: #else
                   2833:     union {
                   2834:        u_char                  buf[NG_BPF_HOOKPROG_SIZE(TCPSYN_PROG_LEN)];
                   2835:        struct ng_bpf_hookprog  hprog;
                   2836:     }                          u;
                   2837:     struct ng_bpf_hookprog     *const hp = &u.hprog;
                   2838:     char                       hook[NG_HOOKSIZ];
                   2839: 
                   2840:     /* Setup programs for ng_bpf hooks */
                   2841:     snprintf(hook, sizeof(hook), "i%d", b->id);
                   2842: 
                   2843:     memset(&u, 0, sizeof(u));
                   2844:     strcpy(hp->thisHook, "ppp");
                   2845:     hp->bpf_prog_len = TCPSYN_PROG_LEN;
                   2846:     memcpy(&hp->bpf_prog, &gTCPSYNProg,
                   2847:         TCPSYN_PROG_LEN * sizeof(*gTCPSYNProg));
                   2848:     strcpy(hp->ifMatch, MPD_HOOK_TCPMSS_IN);
                   2849:     strcpy(hp->ifNotMatch, "iface");
                   2850: 
                   2851:     if (NgSendMsg(gLinksCsock, hook, NGM_BPF_COOKIE,
                   2852:            NGM_BPF_SET_PROGRAM, hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0)
                   2853:        Perror("[%s] can't set %s node program", b->name, NG_BPF_NODE_TYPE);
                   2854: 
                   2855:     memset(&u, 0, sizeof(u));
                   2856:     strcpy(hp->thisHook, MPD_HOOK_TCPMSS_IN);
                   2857:     hp->bpf_prog_len = NOMATCH_PROG_LEN;
                   2858:     memcpy(&hp->bpf_prog, &gNoMatchProg,
                   2859:         NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
                   2860:     strcpy(hp->ifMatch, "ppp");
                   2861:     strcpy(hp->ifNotMatch, "ppp");
                   2862: 
                   2863:     if (NgSendMsg(gLinksCsock, hook, NGM_BPF_COOKIE,
                   2864:            NGM_BPF_SET_PROGRAM, hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0)
                   2865:        Perror("[%s] can't set %s node program", b->name, NG_BPF_NODE_TYPE);
                   2866: 
                   2867:     snprintf(hook, sizeof(hook), "o%d", b->id);
                   2868:     memset(&u, 0, sizeof(u));
                   2869:     strcpy(hp->thisHook, "iface");
                   2870:     hp->bpf_prog_len = TCPSYN_PROG_LEN;
                   2871:     memcpy(&hp->bpf_prog, &gTCPSYNProg,
                   2872:         TCPSYN_PROG_LEN * sizeof(*gTCPSYNProg));
                   2873:     strcpy(hp->ifMatch, MPD_HOOK_TCPMSS_OUT);
                   2874:     strcpy(hp->ifNotMatch, "ppp");
                   2875: 
                   2876:     if (NgSendMsg(gLinksCsock, hook, NGM_BPF_COOKIE,
                   2877:            NGM_BPF_SET_PROGRAM, hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0)
                   2878:        Perror("[%s] can't set %s node program", b->name, NG_BPF_NODE_TYPE);
                   2879: 
                   2880:     memset(&u, 0, sizeof(u));
                   2881:     strcpy(hp->thisHook, MPD_HOOK_TCPMSS_OUT);
                   2882:     hp->bpf_prog_len = NOMATCH_PROG_LEN;
                   2883:     memcpy(&hp->bpf_prog, &gNoMatchProg,
                   2884:         NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
                   2885:     strcpy(hp->ifMatch, "iface");
                   2886:     strcpy(hp->ifNotMatch, "iface");
                   2887: 
                   2888:     if (NgSendMsg(gLinksCsock, hook, NGM_BPF_COOKIE,
                   2889:            NGM_BPF_SET_PROGRAM, hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0)
                   2890:        Perror("[%s] can't set %s node program", b->name, NG_BPF_NODE_TYPE);
                   2891: 
                   2892: #endif /* USE_NG_TCPMSS */
                   2893: }
                   2894: 
                   2895: static void
                   2896: IfaceShutdownMSS(Bund b)
                   2897: {
                   2898:        char    path[NG_PATHSIZ];
                   2899: 
                   2900: #ifdef USE_NG_TCPMSS
                   2901:        snprintf(path, sizeof(path), "mpd%d-%s-mss:", gPid, b->name);
                   2902:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   2903: #else
                   2904:        snprintf(path, sizeof(path), "i%d", b->id);
                   2905:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   2906: #endif
                   2907: }
                   2908: #endif /* defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF)) */
                   2909: 
                   2910: #ifdef USE_NG_BPF
                   2911: static int
                   2912: IfaceInitLimits(Bund b, char *path, char *hook)
                   2913: {
                   2914:     struct ngm_mkpeer  mp;
                   2915:     struct ngm_name    nm;
                   2916: 
                   2917:     if (b->params.acl_limits[0] || b->params.acl_limits[1]) {
                   2918: 
                   2919:        Log(LG_IFACE2, ("[%s] IFACE: Connecting limits", b->name));
                   2920:   
                   2921:        /* Create a bpf node for traffic filtering. */
                   2922:        strcpy(mp.type, NG_BPF_NODE_TYPE);
                   2923:        strlcpy(mp.ourhook, hook, sizeof(mp.ourhook));
                   2924:        strcpy(mp.peerhook, "ppp");
                   2925:        if (NgSendMsg(gLinksCsock, path,
                   2926:                NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   2927:            Perror("can't create %s node at \"%s\"->\"%s\"",
                   2928:                NG_BPF_NODE_TYPE, path, mp.ourhook);
                   2929:            goto fail;
                   2930:        }
                   2931: 
                   2932:        strlcat(path, ".", NG_PATHSIZ);
                   2933:        strlcat(path, hook, NG_PATHSIZ);
                   2934:        strcpy(hook, "iface");
                   2935: 
                   2936:        b->iface.limitID = NgGetNodeID(gLinksCsock, path);
                   2937:        if (b->iface.limitID == 0)
                   2938:            Perror("can't get limits %s node ID", NG_BPF_NODE_TYPE);
                   2939: 
                   2940:        /* Set the new node's name. */
                   2941:        snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-lim", gPid, b->name);
                   2942:        if (NgSendMsg(gLinksCsock, path,
                   2943:                NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   2944:            Perror("can't name limits %s node", NG_BPF_NODE_TYPE);
                   2945:            goto fail;
                   2946:        }
                   2947: 
                   2948:     }
                   2949: 
                   2950:     return (0);
                   2951: fail:
                   2952:     return (-1);
                   2953: }
                   2954: 
                   2955: /*
                   2956:  * BundConfigLimits()
                   2957:  *
                   2958:  * Configure the bpf & car nodes.
                   2959:  */
                   2960: 
                   2961: static void
                   2962: IfaceSetupLimits(Bund b)
                   2963: {
                   2964: #define        ACL_MAX_PROGLEN 65536
                   2965:     union {
                   2966:        u_char                  buf[NG_BPF_HOOKPROG_SIZE(ACL_MAX_PROGLEN)];
                   2967:        struct ng_bpf_hookprog  hprog;
                   2968:     }                          *hpu;
                   2969:     struct ng_bpf_hookprog     *hp;
                   2970:     struct ngm_connect  cn;
                   2971:     int                        i;
                   2972:     
                   2973:     hpu = Malloc(MB_IFACE, sizeof(*hpu));
                   2974:     hp = &hpu->hprog;
                   2975: 
                   2976:     if (b->params.acl_limits[0] || b->params.acl_limits[1]) {
                   2977:        char            path[NG_PATHSIZ];
                   2978:        int             num, dir;
                   2979: 
                   2980:        snprintf(path, sizeof(path), "mpd%d-%s-lim:", gPid, b->name);
                   2981:        
                   2982:        for (dir = 0; dir < 2; dir++) {
                   2983:            char        inhook[2][NG_HOOKSIZ];
                   2984:            char        inhookn[2][NG_HOOKSIZ];
                   2985:            char        outhook[NG_HOOKSIZ];
                   2986:            struct acl  *l;
                   2987: 
                   2988:            if (dir == 0) {
                   2989:                strcpy(inhook[0], "ppp");
                   2990:                strcpy(outhook, "iface");
                   2991:            } else {
                   2992:                strcpy(inhook[0], "iface");
                   2993:                strcpy(outhook, "ppp");
                   2994:            }
                   2995:            strcpy(inhook[1], "");
                   2996:            num = 0;
                   2997:            for (l = b->params.acl_limits[dir]; l; l = l->next) {
                   2998:                char            str[ACL_LEN];
                   2999: #define        ACL_MAX_PARAMS  7       /* one more then max number of arguments */
                   3000:                int             ac;
                   3001:                char            *av[ACL_MAX_PARAMS];
                   3002:                int             p;
                   3003:                char            stathook[NG_HOOKSIZ];
                   3004:                struct svcs     *ss = NULL;
                   3005:                struct svcssrc  *sss = NULL;
                   3006: 
                   3007:                Log(LG_IFACE2, ("[%s] IFACE: limit %s#%d%s%s: '%s'",
                   3008:                    b->name, (dir?"out":"in"), l->number,
                   3009:                    ((l->name[0])?"#":""), l->name, l->rule));
                   3010:                strlcpy(str, l->rule, sizeof(str));
                   3011:                ac = ParseLine(str, av, ACL_MAX_PARAMS, 0);
                   3012:                if (ac < 1 || ac >= ACL_MAX_PARAMS) {
                   3013:                    Log(LG_ERR, ("[%s] IFACE: incorrect limit: '%s'",
                   3014:                        b->name, l->rule));
                   3015:                    continue;
                   3016:                }
                   3017:                
                   3018:                stathook[0] = 0;
                   3019:                memset(hpu, 0, sizeof(hpu));
                   3020:                /* Prepare filter */
                   3021:                if (strcasecmp(av[0], "all") == 0) {
                   3022:                    hp->bpf_prog_len = MATCH_PROG_LEN;
                   3023:                    memcpy(&hp->bpf_prog, &gMatchProg,
                   3024:                        MATCH_PROG_LEN * sizeof(*gMatchProg));
                   3025:                } else if (strncasecmp(av[0], "flt", 3) == 0) {
                   3026:                    struct acl  *f;
                   3027:                    int         flt;
                   3028:                    
                   3029:                    flt = atoi(av[0] + 3);
                   3030:                    if (flt <= 0 || flt > ACL_FILTERS) {
                   3031:                        Log(LG_ERR, ("[%s] IFACE: incorrect filter number: '%s'",
                   3032:                            b->name, av[0]));
                   3033:                    } else if ((f = b->params.acl_filters[flt - 1]) == NULL &&
                   3034:                        (f = acl_filters[flt - 1]) == NULL) {
                   3035:                        Log(LG_ERR, ("[%s] IFACE: Undefined filter: '%s'",
                   3036:                            b->name, av[0]));
                   3037:                    } else {
                   3038:                        struct bpf_program pr;
                   3039:                        char            *buf;
                   3040:                        int             bufbraces;
                   3041: 
                   3042: #define ACL_BUF_SIZE   256*1024
                   3043:                        buf = Malloc(MB_IFACE, ACL_BUF_SIZE);
                   3044:                        buf[0] = 0;
                   3045:                        bufbraces = 0;
                   3046:                        while (f) {
                   3047:                            char        *b1, *b2, *sbuf;
                   3048:                            sbuf = Mstrdup(MB_IFACE, f->rule);
                   3049:                            b2 = sbuf;
                   3050:                            b1 = strsep(&b2, " ");
                   3051:                            if (b2 != NULL) {
                   3052:                                if (strcasecmp(b1, "match") == 0) {
                   3053:                                    strlcat(buf, "( ", ACL_BUF_SIZE);
                   3054:                                    strlcat(buf, b2, ACL_BUF_SIZE);
                   3055:                                    strlcat(buf, " ) ", ACL_BUF_SIZE);
                   3056:                                    if (f->next) {
                   3057:                                        strlcat(buf, "|| ( ", ACL_BUF_SIZE);
                   3058:                                        bufbraces++;
                   3059:                                    }
                   3060:                                } else if (strcasecmp(b1, "nomatch") == 0) {
                   3061:                                    strlcat(buf, "( not ( ", ACL_BUF_SIZE);
                   3062:                                    strlcat(buf, b2, ACL_BUF_SIZE);
                   3063:                                    strlcat(buf, " ) ) ", ACL_BUF_SIZE);
                   3064:                                    if (f->next) {
                   3065:                                        strlcat(buf, "&& ( ", ACL_BUF_SIZE);
                   3066:                                        bufbraces++;
                   3067:                                    }
                   3068:                                } else {
                   3069:                                    Log(LG_ERR, ("[%s] IFACE: filter action '%s' is unknown",
                   3070:                                        b->name, b1));
                   3071:                                }
                   3072:                            };
                   3073:                            Freee(sbuf);
                   3074:                            f = f->next;
                   3075:                        }
                   3076:                        for (i = 0; i < bufbraces; i++)
                   3077:                            strlcat(buf, ") ", ACL_BUF_SIZE);
                   3078:                        Log(LG_IFACE2, ("[%s] IFACE: flt%d: '%s'",
                   3079:                            b->name, flt, buf));
                   3080:                        
                   3081:                        if (pcap_compile_nopcap((u_int)-1, DLT_RAW, &pr, buf, 1, 0xffffff00)) {
                   3082:                            Log(LG_ERR, ("[%s] IFACE: filter '%s' compilation error",
                   3083:                                b->name, av[0]));
                   3084:                            /* Incorrect matches nothing. */
                   3085:                            hp->bpf_prog_len = NOMATCH_PROG_LEN;
                   3086:                            memcpy(&hp->bpf_prog, &gNoMatchProg,
                   3087:                                NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
                   3088:                        } else if (pr.bf_len > ACL_MAX_PROGLEN) {
                   3089:                            Log(LG_ERR, ("[%s] IFACE: filter '%s' is too long",
                   3090:                                b->name, av[0]));
                   3091:                            pcap_freecode(&pr);
                   3092:                            /* Incorrect matches nothing. */
                   3093:                            hp->bpf_prog_len = NOMATCH_PROG_LEN;
                   3094:                            memcpy(&hp->bpf_prog, &gNoMatchProg,
                   3095:                                NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
                   3096:                        } else {
                   3097:                            hp->bpf_prog_len = pr.bf_len;
                   3098:                            memcpy(&hp->bpf_prog, pr.bf_insns,
                   3099:                                pr.bf_len * sizeof(struct bpf_insn));
                   3100:                            pcap_freecode(&pr);
                   3101:                        }
                   3102:                        Freee(buf);
                   3103:                    }
                   3104:                } else {
                   3105:                    Log(LG_ERR, ("[%s] IFACE: incorrect filter: '%s'",
                   3106:                        b->name, av[0]));
                   3107:                    /* Incorrect matches nothing. */
                   3108:                    hp->bpf_prog_len = NOMATCH_PROG_LEN;
                   3109:                    memcpy(&hp->bpf_prog, &gNoMatchProg,
                   3110:                        NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
                   3111:                }
                   3112:                
                   3113:                /* Prepare action */
                   3114:                p = 1;
                   3115:                if (ac == 1) {
                   3116:                    if (!l->next) {
                   3117:                        strcpy(hp->ifMatch, outhook);
                   3118:                        strcpy(inhookn[0], "");
                   3119:                    } else {
                   3120:                        sprintf(hp->ifMatch, "%d-%d-m", dir, num);
                   3121:                        sprintf(inhookn[0], "%d-%d-mi", dir, num);
                   3122: 
                   3123:                        /* Connect nomatch hook to bpf itself. */
                   3124:                        strcpy(cn.ourhook, hp->ifMatch);
                   3125:                        strcpy(cn.path, path);
                   3126:                        strcpy(cn.peerhook, inhookn[0]);
                   3127:                        if (NgSendMsg(gLinksCsock, path,
                   3128:                                NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                   3129:                            Perror("[%s] IFACE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   3130:                                b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   3131:                        }
                   3132:                        strcpy(stathook, inhookn[0]);
                   3133:                    }
                   3134:                } else if (strcasecmp(av[p], "pass") == 0) {
                   3135:                    strcpy(hp->ifMatch, outhook);
                   3136:                    strcpy(inhookn[0], "");
                   3137:                } else if (strcasecmp(av[p], "deny") == 0) {
                   3138:                    strcpy(hp->ifMatch, "deny");
                   3139:                    strcpy(inhookn[0], "");
                   3140: #ifdef USE_NG_CAR
                   3141:                } else if ((strcasecmp(av[p], "shape") == 0) ||
                   3142:                           (strcasecmp(av[p], "rate-limit") == 0)) {
                   3143:                    struct ngm_mkpeer   mp;
                   3144:                    struct ng_car_bulkconf car;
                   3145:                    char                tmppath[NG_PATHSIZ];
                   3146: 
                   3147:                    sprintf(hp->ifMatch, "%d-%d-m", dir, num);
                   3148: 
                   3149:                    /* Create a car node for traffic shaping. */
                   3150:                    strcpy(mp.type, NG_CAR_NODE_TYPE);
                   3151:                    snprintf(mp.ourhook, sizeof(mp.ourhook), "%d-%d-m", dir, num);
                   3152:                    strcpy(mp.peerhook, ((dir == 0)?NG_CAR_HOOK_LOWER:NG_CAR_HOOK_UPPER));
                   3153:                    if (NgSendMsg(gLinksCsock, path,
                   3154:                            NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   3155:                        Perror("[%s] IFACE: can't create %s node at \"%s\"->\"%s\"", 
                   3156:                            b->name, NG_CAR_NODE_TYPE, path, mp.ourhook);
                   3157:                    }
                   3158: 
                   3159:                    snprintf(tmppath, sizeof(tmppath), "%s%d-%d-m", path, dir, num);
                   3160: 
                   3161:                    /* Connect car to bpf. */
                   3162:                    snprintf(cn.ourhook, sizeof(cn.ourhook), "%d-%d-mi", dir, num);
                   3163:                    strlcpy(cn.path, tmppath, sizeof(cn.path));
                   3164:                    strcpy(cn.peerhook, ((dir == 0)?NG_CAR_HOOK_UPPER:NG_CAR_HOOK_LOWER));
                   3165:                    if (NgSendMsg(gLinksCsock, path,
                   3166:                            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                   3167:                        Perror("[%s] IFACE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   3168:                            b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   3169:                    }
                   3170:                        
                   3171:                    bzero(&car, sizeof(car));
                   3172:                        
                   3173:                    if (strcasecmp(av[p], "shape") == 0) {
                   3174:                        car.upstream.mode = NG_CAR_SHAPE;
                   3175:                    } else {
                   3176:                        car.upstream.mode = NG_CAR_RED;
                   3177:                    }
                   3178:                    p++;
                   3179: 
                   3180:                    if ((ac > p) && (av[p][0] >= '0') && (av[p][0] <= '9')) {
                   3181:                        car.upstream.cir = atol(av[p]);
                   3182:                        p++;
                   3183:                        if ((ac > p) && (av[p][0] >= '0') && (av[p][0] <= '9')) {
                   3184:                            car.upstream.cbs = atol(av[p]);
                   3185:                            p++;
                   3186:                            if ((ac > p) && (av[p][0] >= '0') && (av[p][0] <= '9')) {
                   3187:                                car.upstream.ebs = atol(av[p]);
                   3188:                                p++;
                   3189:                            } else {
                   3190:                                car.upstream.ebs = car.upstream.cbs * 2;
                   3191:                            }
                   3192:                        } else {
                   3193:                            car.upstream.cbs = car.upstream.cir / 8;
                   3194:                            car.upstream.ebs = car.upstream.cbs * 2;
                   3195:                        }
                   3196:                    } else {
                   3197:                        car.upstream.cir = 8000;
                   3198:                        car.upstream.cbs = car.upstream.cir / 8;
                   3199:                        car.upstream.ebs = car.upstream.cbs * 2;
                   3200:                    }
                   3201:                    car.upstream.green_action = NG_CAR_ACTION_FORWARD;
                   3202:                    car.upstream.yellow_action = NG_CAR_ACTION_FORWARD;
                   3203:                    car.upstream.red_action = NG_CAR_ACTION_DROP;
                   3204:                        
                   3205:                    car.downstream = car.upstream;
                   3206:                                                
                   3207:                    if (NgSendMsg(gLinksCsock, tmppath,
                   3208:                            NGM_CAR_COOKIE, NGM_CAR_SET_CONF, &car, sizeof(car)) < 0) {
                   3209:                        Perror("[%s] IFACE: can't set %s configuration",
                   3210:                            b->name, NG_CAR_NODE_TYPE);
                   3211:                    }
                   3212:                        
                   3213:                    if (ac > p) {
                   3214:                        if (strcasecmp(av[p], "pass") == 0) {
                   3215:                            union {
                   3216:                                u_char  buf[NG_BPF_HOOKPROG_SIZE(MATCH_PROG_LEN)];
                   3217:                                struct ng_bpf_hookprog  hprog;
                   3218:                            } hpu1;
                   3219:                            struct ng_bpf_hookprog      *const hp1 = &hpu1.hprog;
                   3220: 
                   3221:                            memset(&hpu1, 0, sizeof(hpu1));
                   3222:                            strcpy(hp1->ifMatch, outhook);
                   3223:                            strcpy(hp1->ifNotMatch, outhook);
                   3224:                            hp1->bpf_prog_len = MATCH_PROG_LEN;
                   3225:                            memcpy(&hp1->bpf_prog, &gMatchProg,
                   3226:                                MATCH_PROG_LEN * sizeof(*gMatchProg));
                   3227:                            sprintf(hp1->thisHook, "%d-%d-mi", dir, num);
                   3228:                            if (NgSendMsg(gLinksCsock, path, NGM_BPF_COOKIE, NGM_BPF_SET_PROGRAM,
                   3229:                                    hp1, NG_BPF_HOOKPROG_SIZE(hp1->bpf_prog_len)) < 0) {
                   3230:                                Perror("[%s] IFACE: can't set %s node program",
                   3231:                                    b->name, NG_BPF_NODE_TYPE);
                   3232:                            }
                   3233:                                                    
                   3234:                            strcpy(stathook, hp1->thisHook);
                   3235:                            strcpy(inhookn[0], "");
                   3236:                        } else {
                   3237:                            Log(LG_ERR, ("[%s] IFACE: unknown action: '%s'",
                   3238:                                b->name, av[p]));
                   3239:                            strcpy(inhookn[0], "");
                   3240:                        }
                   3241:                    } else {
                   3242:                        sprintf(inhookn[0], "%d-%d-mi", dir, num);
                   3243:                        strcpy(stathook, inhookn[0]);
                   3244:                    }
                   3245: #endif /* USE_NG_CAR */
                   3246:                } else {
                   3247:                    Log(LG_ERR, ("[%s] IFACE: unknown action: '%s'",
                   3248:                        b->name, av[1]));
                   3249:                    strcpy(inhookn[0], "");
                   3250:                }
                   3251:                
                   3252:                /* Prepare nomatch */
                   3253:                if (l->next && strcasecmp(av[0], "all")) {
                   3254:                    /* If there is next limit and there is possible nomatch,
                   3255:                     * then pass nomatch there. */
                   3256:                    sprintf(hp->ifNotMatch, "%d-%d-n", dir, num);
                   3257:                    sprintf(inhookn[1], "%d-%d-ni", dir, num);
                   3258: 
                   3259:                    /* Connect nomatch hook to bpf itself. */
                   3260:                    strcpy(cn.ourhook, hp->ifNotMatch);
                   3261:                    strcpy(cn.path, path);
                   3262:                    strcpy(cn.peerhook, inhookn[1]);
                   3263:                    if (NgSendMsg(gLinksCsock, path,
                   3264:                            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                   3265:                        Perror("[%s] IFACE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                   3266:                            b->name, path, cn.ourhook, cn.path, cn.peerhook);
                   3267:                    }
                   3268:                } else {
                   3269:                    /* There is no next limit, pass nomatch. */
                   3270:                    strcpy(hp->ifNotMatch, outhook);
                   3271:                    strcpy(inhookn[1], "");
                   3272:                }
                   3273:                
                   3274:                /* Remember how to collect stats for this limit */
                   3275:                if (l->name[0]) {
                   3276:                    SLIST_FOREACH(ss, &b->iface.ss[dir], next) {
                   3277:                        if (strcmp(ss->name, l->name) == 0)
                   3278:                            break;
                   3279:                    }
                   3280:                    if (ss == NULL) {
                   3281:                        ss = Malloc(MB_IFACE, sizeof(*ss));
                   3282:                        strlcpy(ss->name, l->name, sizeof(ss->name));
                   3283:                        SLIST_INIT(&ss->src);
                   3284:                        SLIST_INSERT_HEAD(&b->iface.ss[dir], ss, next);
                   3285:                    }
                   3286:                    if (stathook[0]) {
                   3287:                        sss = Malloc(MB_IFACE, sizeof(*sss));
                   3288:                        strlcpy(sss->hook, stathook, sizeof(sss->hook));
                   3289:                        sss->type = SSSS_IN;
                   3290:                        SLIST_INSERT_HEAD(&ss->src, sss, next);
                   3291:                    }
                   3292:                }
                   3293:                
                   3294:                for (i = 0; i < 2; i++) {
                   3295:                    if (inhook[i][0] != 0) {
                   3296:                        if (l->name[0] && !stathook[0]) {
                   3297:                            sss = Malloc(MB_IFACE, sizeof(*sss));
                   3298:                            strlcpy(sss->hook, inhook[i], sizeof(sss->hook));
                   3299:                            sss->type = SSSS_MATCH;
                   3300:                            SLIST_INSERT_HEAD(&ss->src, sss, next);
                   3301:                        }
                   3302:                
                   3303:                        strcpy(hp->thisHook, inhook[i]);
                   3304:                        if (NgSendMsg(gLinksCsock, path, NGM_BPF_COOKIE, NGM_BPF_SET_PROGRAM,
                   3305:                                hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0) {
                   3306:                            Perror("[%s] IFACE: can't set %s node program",
                   3307:                                b->name, NG_BPF_NODE_TYPE);
                   3308:                        }
                   3309:                    }
                   3310:                    strcpy(inhook[i], inhookn[i]);
                   3311:                }
                   3312: 
                   3313:                num++;
                   3314:            }
                   3315:        
                   3316:            /* Connect left hooks to output */
                   3317:            for (i = 0; i < 2; i++) {
                   3318:                if (inhook[i][0] != 0) {
                   3319:                    memset(hpu, 0, sizeof(*hpu));
                   3320:                    strcpy(hp->thisHook, inhook[i]);
                   3321:                    hp->bpf_prog_len = MATCH_PROG_LEN;
                   3322:                    memcpy(&hp->bpf_prog, &gMatchProg,
                   3323:                        MATCH_PROG_LEN * sizeof(*gMatchProg));
                   3324:                    strcpy(hp->ifMatch, outhook);
                   3325:                    strcpy(hp->ifNotMatch, outhook);
                   3326:                    if (NgSendMsg(gLinksCsock, path, NGM_BPF_COOKIE, NGM_BPF_SET_PROGRAM, 
                   3327:                            hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0) {
                   3328:                        Perror("[%s] IFACE: can't set %s node %s %s program (2)",
                   3329:                            b->name, NG_BPF_NODE_TYPE, path, hp->thisHook);
                   3330:                    }
                   3331:                }
                   3332:            }
                   3333:        }
                   3334:     }
                   3335:     Freee(hpu);
                   3336: }
                   3337: 
                   3338: static void
                   3339: IfaceShutdownLimits(Bund b)
                   3340: {
                   3341:     char path[NG_PATHSIZ];
                   3342:     struct svcs *ss;
                   3343:     struct svcssrc *sss;
                   3344:     struct svcstat curstats;
                   3345:     int                i;
                   3346: 
                   3347:     if (b->n_up > 0) {
                   3348:        bzero(&curstats, sizeof(curstats));
                   3349:        IfaceGetStats(b, &curstats);
                   3350:        IfaceAddStats(&b->iface.prevstats, &curstats);
                   3351:        IfaceFreeStats(&curstats);
                   3352:     }
                   3353: 
                   3354:     if (b->params.acl_limits[0] || b->params.acl_limits[1]) {
                   3355:        snprintf(path, sizeof(path), "[%x]:", b->iface.limitID);
                   3356:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   3357:     }
                   3358: 
                   3359:     for (i = 0; i < ACL_DIRS; i++) {
                   3360:        while ((ss = SLIST_FIRST(&b->iface.ss[i])) != NULL) {
                   3361:            while ((sss = SLIST_FIRST(&ss->src)) != NULL) {
                   3362:                SLIST_REMOVE_HEAD(&ss->src, next);
                   3363:                Freee(sss);
                   3364:            }
                   3365:            SLIST_REMOVE_HEAD(&b->iface.ss[i], next);
                   3366:            Freee(ss);
                   3367:        }
                   3368:     }
                   3369: }
                   3370: 
                   3371: void
                   3372: IfaceGetStats(Bund b, struct svcstat *stat)
                   3373: {
                   3374:     char path[NG_PATHSIZ];
                   3375:     struct svcs        *ss;
                   3376:     struct svcssrc     *sss;
                   3377:     int        dir;
                   3378: 
                   3379:     union {
                   3380:         u_char          buf[sizeof(struct ng_mesg) + sizeof(struct ng_bpf_hookstat)];
                   3381:        struct ng_mesg  reply;
                   3382:     }                   u;
                   3383:     struct ng_bpf_hookstat     *const hs = (struct ng_bpf_hookstat *)(void *)u.reply.data;
                   3384: 
                   3385:     snprintf(path, sizeof(path), "[%x]:", b->iface.limitID);
                   3386:     for (dir = 0; dir < ACL_DIRS; dir++) {
                   3387:        SLIST_FOREACH(ss, &b->iface.ss[dir], next) {
                   3388:            struct svcstatrec *ssr;
                   3389:        
                   3390:            SLIST_FOREACH(ssr, &stat->stat[dir], next) {
                   3391:                if (strcmp(ssr->name, ss->name) == 0)
                   3392:                    break;
                   3393:            }
                   3394:            if (!ssr) {
                   3395:                ssr = Malloc(MB_IFACE, sizeof(*ssr));
                   3396:                strlcpy(ssr->name, ss->name, sizeof(ssr->name));
                   3397:                SLIST_INSERT_HEAD(&stat->stat[dir], ssr, next);
                   3398:            }
                   3399:     
                   3400:            SLIST_FOREACH(sss, &ss->src, next) {
                   3401:                if (NgSendMsg(gLinksCsock, path,
                   3402:                    NGM_BPF_COOKIE, NGM_BPF_GET_STATS, sss->hook, strlen(sss->hook)+1) < 0)
                   3403:                    continue;
                   3404:                if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0)
                   3405:                    continue;
                   3406:                
                   3407:                switch(sss->type) {
                   3408:                case SSSS_IN:
                   3409:                    ssr->Packets += hs->recvFrames;
                   3410:                    ssr->Octets += hs->recvOctets;
                   3411:                    break;
                   3412:                case SSSS_MATCH:
                   3413:                    ssr->Packets += hs->recvMatchFrames;
                   3414:                    ssr->Octets += hs->recvMatchOctets;
                   3415:                    break;
                   3416:                case SSSS_NOMATCH:
                   3417:                    ssr->Packets += hs->recvFrames - hs->recvMatchFrames;
                   3418:                    ssr->Octets += hs->recvOctets - hs->recvMatchOctets;
                   3419:                    break;
                   3420:                case SSSS_OUT:
                   3421:                    ssr->Packets += hs->xmitFrames;
                   3422:                    ssr->Octets += hs->xmitOctets;
                   3423:                    break;
                   3424:                }
                   3425:            }
                   3426:        }
                   3427:     }
                   3428: }
                   3429: 
                   3430: void
                   3431: IfaceAddStats(struct svcstat *stat1, struct svcstat *stat2)
                   3432: {
                   3433:     struct svcstatrec   *ssr1, *ssr2;
                   3434:     int                 dir;
                   3435: 
                   3436:     for (dir = 0; dir < ACL_DIRS; dir++) {
                   3437:        SLIST_FOREACH(ssr2, &stat2->stat[dir], next) {
                   3438:            SLIST_FOREACH(ssr1, &stat1->stat[dir], next)
                   3439:                if (strcmp(ssr1->name, ssr2->name) == 0) {
                   3440:                    break;
                   3441:            }
                   3442:            if (!ssr1) {
                   3443:                ssr1 = Malloc(MB_IFACE, sizeof(*ssr1));
                   3444:                strlcpy(ssr1->name, ssr2->name, sizeof(ssr1->name));
                   3445:                SLIST_INSERT_HEAD(&stat1->stat[dir], ssr1, next);
                   3446:            }
                   3447:            ssr1->Packets += ssr2->Packets;
                   3448:            ssr1->Octets += ssr2->Octets;
                   3449:        }
                   3450:     }
                   3451: }
                   3452: 
                   3453: void
                   3454: IfaceFreeStats(struct svcstat *stat)
                   3455: {
                   3456:     struct svcstatrec   *ssr;
                   3457:     int                 i;
                   3458: 
                   3459:     for (i = 0; i < ACL_DIRS; i++) {
                   3460:        while ((ssr = SLIST_FIRST(&stat->stat[i])) != NULL) {
                   3461:            SLIST_REMOVE_HEAD(&stat->stat[i], next);
                   3462:            Freee(ssr);
                   3463:        }
                   3464:     }
                   3465: }
                   3466: #endif /* USE_NG_BPF */
                   3467: 
                   3468: /*
                   3469:  * IfaceSetName()
                   3470:  */
                   3471: 
                   3472: int
                   3473: IfaceSetName(Bund b, const char * ifname)
                   3474: {
                   3475:     IfaceState const iface = &b->iface;
                   3476:     struct ifreq ifr;
                   3477:     int s;
                   3478: 
                   3479:     /* Do not rename interface on template */
                   3480:     if (b->tmpl)
                   3481:        return(0);
                   3482: 
                   3483:     /* Do not wait ioctl error "file already exist" */
                   3484:     if (strncmp(iface->ifname, ifname, sizeof(iface->ifname)) == 0)
                   3485:        return(0);
                   3486: 
                   3487:     /* Get socket */
                   3488:     if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                   3489:        Log(LG_ERR, ("[%s] IFACE: Can't get socket to set name", b->name));
                   3490:        return(-1);
                   3491:     }
                   3492: 
                   3493:     /* Set name of interface */
                   3494:     memset(&ifr, 0, sizeof(ifr));
                   3495:     strlcpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name));
                   3496:     ifr.ifr_data = (caddr_t)ifname;
                   3497:     Log(LG_IFACE2, ("[%s] IFACE: setting \"%s\" name to \"%s\"",
                   3498:        b->name, iface->ifname, ifname));
                   3499: 
                   3500:     if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
                   3501:        Perror("[%s] IFACE: ioctl(%s, SIOCSIFNAME)", b->name, iface->ifname);
                   3502:        close(s);
                   3503:        return(-1);
                   3504:     }
                   3505: 
                   3506:     close(s);
                   3507:     /* Save name */
                   3508:     strlcpy(iface->ifname, ifname, sizeof(iface->ifname));
                   3509:     return(0);
                   3510: }
                   3511: 
                   3512: #ifdef SIOCSIFDESCR
                   3513: /*
                   3514:  * IfaceSetDescr()
                   3515:  */
                   3516: 
                   3517: int
                   3518: IfaceSetDescr(Bund b, const char * ifdescr)
                   3519: {
                   3520:     IfaceState const iface = &b->iface;
                   3521:     struct     ifreq ifr;
                   3522:     int                s, ifdescr_maxlen;
                   3523:     char       *newdescr;
                   3524:     size_t     sz = sizeof(int);
                   3525: 
                   3526:     if (b->tmpl) {
                   3527:        Log(LG_ERR, ("Impossible ioctl(SIOCSIFDESCR) on template"));
                   3528:        return(-1);
                   3529:     }
                   3530: 
                   3531:     if (sysctlbyname("net.ifdescr_maxlen", &ifdescr_maxlen, &sz, NULL, 0) < 0) {
                   3532:        Perror("[%s] IFACE: sysctl net.ifdescr_maxlen  failed", b->name);
                   3533:        return(-1);
                   3534:     }
                   3535: 
                   3536:     if (ifdescr_maxlen < strlen(ifdescr) + 1) {
                   3537:        Log(LG_ERR, ("[%s] IFACE: Description too long, >%d characters",
                   3538:            b->name, ifdescr_maxlen-1));
                   3539:        return(-1);
                   3540:     }
                   3541: 
                   3542:     /* Get socket */
                   3543:     if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                   3544:        Log(LG_ERR, ("[%s] IFACE: Can't get socket to set description", b->name));
                   3545:        return(-1);
                   3546:     }
                   3547: 
                   3548:     /* Set description of interface */
                   3549:     memset(&ifr, 0, sizeof(ifr));
                   3550:     strlcpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name));
                   3551:     ifr.ifr_buffer.length = strlen(ifdescr) + 1;
                   3552:     if (ifr.ifr_buffer.length == 1) {
                   3553:        ifr.ifr_buffer.buffer = newdescr = NULL;
                   3554:        ifr.ifr_buffer.length = 0;
                   3555:        Log(LG_IFACE2, ("[%s] IFACE: clearing \"%s\" description",
                   3556:            b->name, iface->ifname));
                   3557:     } else {
                   3558:        newdescr = Mstrdup(MB_IFACE, ifdescr);
                   3559:        ifr.ifr_buffer.buffer = newdescr;
                   3560:        Log(LG_IFACE2, ("[%s] IFACE: setting \"%s\" description to \"%s\"",
                   3561:            b->name, iface->ifname, ifdescr));
                   3562:     }
                   3563: 
                   3564:     if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) {
                   3565:        Perror("[%s] IFACE: ioctl(%s, SIOCSIFDESCR)", b->name, iface->ifname);
                   3566:        Freee(newdescr);
                   3567:        close(s);
                   3568:        return(-1);
                   3569:     }
                   3570:     Freee(newdescr);
                   3571:     close(s);
                   3572:     return(0);
                   3573: }
                   3574: #endif /* SIOCSIFDESCR */
                   3575: #ifdef SIOCAIFGROUP
                   3576: /*
                   3577:  * IfaceAddGroup()
                   3578:  */
                   3579: 
                   3580: int
                   3581: IfaceAddGroup(Bund b, const char * ifgroup)
                   3582: {
                   3583:     IfaceState const iface = &b->iface;
                   3584:     struct ifgroupreq  ifgr;
                   3585:     int        s, i;
                   3586: 
                   3587:     /* Do not add group on template */
                   3588:     if (b->tmpl)
                   3589:        return(0);
                   3590: 
                   3591:     if (ifgroup[0] && isdigit(ifgroup[strlen(ifgroup) - 1])) {
                   3592:        Perror("[%s] IFACE: groupnames may not end in a digit", b->name);
                   3593:        return(-1);
                   3594:     }
                   3595: 
                   3596:     /* Get socket */
                   3597:     if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                   3598:        Perror("[%s] IFACE: Can't get socket to add group", b->name);
                   3599:        return(-1);
                   3600:     }
                   3601: 
                   3602:     /* Add interface group */
                   3603:     memset(&ifgr, 0, sizeof(ifgr));
                   3604:     strlcpy(ifgr.ifgr_name, iface->ifname, sizeof(ifgr.ifgr_name));
                   3605:     strlcpy(ifgr.ifgr_group, ifgroup, sizeof(ifgr.ifgr_group));
                   3606: 
                   3607:     Log(LG_IFACE2, ("[%s] IFACE: adding interface %s to group %s",
                   3608:        b->name, iface->ifname, ifgroup));
                   3609: 
                   3610:     i = ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr);
                   3611:     if (i < 0 && i != EEXIST) {
                   3612:        Perror("[%s] IFACE: ioctl(%s, SIOCAIFGROUP)", b->name, iface->ifname);
                   3613:         close(s);
                   3614:         return(-1);
                   3615:     }
                   3616: 
                   3617:     close(s);
                   3618:     return(0);
                   3619: }
                   3620: 
                   3621: /*
                   3622:  * IfaceDelGroup()
                   3623:  */
                   3624: int
                   3625: IfaceDelGroup(Bund b, const char * ifgroup)
                   3626: {
                   3627:     IfaceState const iface = &b->iface;
                   3628:     struct ifgroupreq  ifgr;
                   3629:     int        s;
                   3630: 
                   3631:     /* Get socket */
                   3632:     if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                   3633:        Perror("[%s] IFACE: Can't get socket to delete from group", b->name);
                   3634:        return(-1);
                   3635:     }
                   3636: 
                   3637:     if (ifgroup[0] && isdigit(ifgroup[strlen(ifgroup) - 1])) {
                   3638:        Perror("[%s] IFACE: groupnames may not end in a digit", b->name);
                   3639:        return(-1);
                   3640:     }
                   3641: 
                   3642:     /* Set interface group */
                   3643:     memset(&ifgr, 0, sizeof(ifgr));
                   3644:     strlcpy(ifgr.ifgr_name, iface->ifname, sizeof(ifgr.ifgr_name));
                   3645:     strlcpy(ifgr.ifgr_group, ifgroup, sizeof(ifgr.ifgr_group));
                   3646: 
                   3647:     Log(LG_IFACE2, ("[%s] IFACE: remove interface %s from group %s",
                   3648:        b->name, iface->ifname, ifgroup));
                   3649: 
                   3650:     if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1) {
                   3651:        Perror("[%s] IFACE: ioctl(%s, SIOCDIFGROUP)", b->name, iface->ifname);
                   3652:        close(s);
                   3653:        return(-1);
                   3654:     }
                   3655:     close(s);
                   3656:     return(0);
                   3657: }
                   3658: #endif

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