Annotation of embedaddon/mpd/src/iface.c, revision 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>