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

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