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

1.1       misho       1: 
                      2: /*
                      3:  * bund.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:  * Bundle handling stuff
                     10:  */
                     11: 
                     12: #include "ppp.h"
                     13: #include "bund.h"
                     14: #include "ipcp.h"
                     15: #include "ccp.h"
                     16: #include "mp.h"
                     17: #include "iface.h"
                     18: #include "link.h"
                     19: #include "msg.h"
                     20: #include "ngfunc.h"
                     21: #include "log.h"
                     22: #include "util.h"
                     23: #include "input.h"
                     24: 
                     25: #include <netgraph.h>
                     26: #include <netgraph/ng_message.h>
                     27: #include <netgraph/ng_socket.h>
                     28: #include <netgraph/ng_iface.h>
                     29: #ifdef USE_NG_VJC
                     30: #include <netgraph/ng_vjc.h>
                     31: #endif
                     32: 
                     33: /*
                     34:  * DEFINITIONS
                     35:  */
                     36: 
                     37:   /* #define DEBUG_BOD */
                     38: 
                     39:   #define BUND_REOPEN_DELAY    3       /* wait this long before closing */
                     40:   #define BUND_REOPEN_PAUSE    3       /* wait this long before re-opening */
                     41: 
                     42:   #define BUND_MIN_TOT_BW      9600
                     43: 
                     44:   /* Set menu options */
                     45:   enum {
                     46:     SET_PERIOD,
                     47:     SET_LOW_WATER,
                     48:     SET_HIGH_WATER,
                     49:     SET_MIN_CONNECT,
                     50:     SET_MIN_DISCONNECT,
                     51:     SET_LINKS,
                     52:     SET_AUTHNAME,
                     53:     SET_PASSWORD,
                     54:     SET_RETRY,
                     55:     SET_ACCEPT,
                     56:     SET_DENY,
                     57:     SET_ENABLE,
                     58:     SET_DISABLE,
                     59:     SET_YES,
                     60:     SET_NO
                     61:   };
                     62: 
                     63: /*
                     64:  * INTERNAL FUNCTIONS
                     65:  */
                     66: 
                     67:   static int   BundNgInit(Bund b);
                     68:   static void  BundNgShutdown(Bund b, int iface, int ppp);
                     69: 
                     70:   static void  BundBmStart(Bund b);
                     71:   static void  BundBmStop(Bund b);
                     72:   static void  BundBmTimeout(void *arg);
                     73: 
                     74:   static void  BundReasses(Bund b);
                     75:   static int   BundSetCommand(Context ctx, int ac, char *av[], void *arg);
                     76: 
                     77:   static void  BundNcpsUp(Bund b);
                     78:   static void  BundNcpsDown(Bund b);
                     79: 
                     80:   static void  BundReOpenLinks(void *arg);
                     81:   static void  BundCloseLink(Link l);
                     82: 
                     83:   static void  BundMsg(int type, void *cookie);
                     84: 
                     85: /*
                     86:  * GLOBAL VARIABLES
                     87:  */
                     88: 
                     89:   struct discrim       self_discrim;
                     90: 
                     91:   const struct cmdtab BundSetCmds[] = {
                     92:     { "period {seconds}",              "BoD sampling period",
                     93:        BundSetCommand, NULL, 2, (void *) SET_PERIOD },
                     94:     { "lowat {percent}",               "BoD low water mark",
                     95:        BundSetCommand, NULL, 2, (void *) SET_LOW_WATER },
                     96:     { "hiwat {percent}",               "BoD high water mark",
                     97:        BundSetCommand, NULL, 2, (void *) SET_HIGH_WATER },
                     98:     { "min-con {seconds}",             "BoD min connected time",
                     99:        BundSetCommand, NULL, 2, (void *) SET_MIN_CONNECT },
                    100:     { "min-dis {seconds}",             "BoD min disconnected time",
                    101:        BundSetCommand, NULL, 2, (void *) SET_MIN_DISCONNECT },
                    102:     { "links {link list ...}",         "Links list for BoD/DoD",
                    103:        BundSetCommand, NULL, 2, (void *) SET_LINKS },
                    104:     { "fsm-timeout {seconds}",         "FSM retry timeout",
                    105:        BundSetCommand, NULL, 2, (void *) SET_RETRY },
                    106:     { "accept {opt ...}",              "Accept option",
                    107:        BundSetCommand, NULL, 2, (void *) SET_ACCEPT },
                    108:     { "deny {opt ...}",                        "Deny option",
                    109:        BundSetCommand, NULL, 2, (void *) SET_DENY },
                    110:     { "enable {opt ...}",              "Enable option",
                    111:        BundSetCommand, NULL, 2, (void *) SET_ENABLE },
                    112:     { "disable {opt ...}",             "Disable option",
                    113:        BundSetCommand, NULL, 2, (void *) SET_DISABLE },
                    114:     { "yes {opt ...}",                 "Enable and accept option",
                    115:        BundSetCommand, NULL, 2, (void *) SET_YES },
                    116:     { "no {opt ...}",                  "Disable and deny option",
                    117:        BundSetCommand, NULL, 2, (void *) SET_NO },
                    118:     { NULL },
                    119:   };
                    120: 
                    121: /*
                    122:  * INTERNAL VARIABLES
                    123:  */
                    124: 
                    125:   static const struct confinfo gConfList[] = {
                    126:     { 0,       BUND_CONF_IPCP,         "ipcp"          },
                    127:     { 0,       BUND_CONF_IPV6CP,       "ipv6cp"        },
                    128:     { 0,       BUND_CONF_COMPRESSION,  "compression"   },
                    129:     { 0,       BUND_CONF_ENCRYPTION,   "encryption"    },
                    130:     { 0,       BUND_CONF_CRYPT_REQD,   "crypt-reqd"    },
                    131:     { 0,       BUND_CONF_BWMANAGE,     "bw-manage"     },
                    132:     { 0,       BUND_CONF_ROUNDROBIN,   "round-robin"   },
                    133:     { 0,       0,                      NULL            },
                    134:   };
                    135: 
                    136: /*
                    137:  * BundOpen()
                    138:  */
                    139: 
                    140: void
                    141: BundOpen(Bund b)
                    142: {
                    143:     REF(b);
                    144:     MsgSend(&b->msgs, MSG_OPEN, b);
                    145: }
                    146: 
                    147: /*
                    148:  * BundClose()
                    149:  */
                    150: 
                    151: void
                    152: BundClose(Bund b)
                    153: {
                    154:     REF(b);
                    155:     MsgSend(&b->msgs, MSG_CLOSE, b);
                    156: }
                    157: 
                    158: /*
                    159:  * BundOpenCmd()
                    160:  */
                    161: 
                    162: int
                    163: BundOpenCmd(Context ctx)
                    164: {
                    165:     if (ctx->bund->tmpl)
                    166:        Error("impossible to open template");
                    167:     BundOpen(ctx->bund);
                    168:     return (0);
                    169: }
                    170: 
                    171: /*
                    172:  * BundCloseCmd()
                    173:  */
                    174: 
                    175: int
                    176: BundCloseCmd(Context ctx)
                    177: {
                    178:     if (ctx->bund->tmpl)
                    179:        Error("impossible to close template");
                    180:     BundClose(ctx->bund);
                    181:     return (0);
                    182: }
                    183: 
                    184: /*
                    185:  * BundJoin()
                    186:  *
                    187:  * This is called when a link enters the NETWORK phase.
                    188:  *
                    189:  * Verify that link is OK to come up as part of it's bundle.
                    190:  * If so, join it to the bundle. Returns FALSE if there's a problem.
                    191:  * If this is the first link to join, and it's not supporting
                    192:  * multi-link, then prevent any further links from joining.
                    193:  *
                    194:  * Right now this is fairly simple minded: you have to define
                    195:  * the links in a bundle first, then stick to that plan. For
                    196:  * a server this might be too restrictive a policy.
                    197:  *
                    198:  * Returns zero if fails, otherwise the new number of up links.
                    199:  */
                    200: 
                    201: int
                    202: BundJoin(Link l)
                    203: {
                    204:     Bund       b, bt;
                    205:     LcpState   const lcp = &l->lcp;
                    206:     int                k;
                    207: 
                    208:     if (gShutdownInProgress) {
                    209:        Log(LG_BUND, ("Shutdown sequence in progress, BundJoin() denied"));
                    210:         return(0);
                    211:     }
                    212: 
                    213:     if (!l->bund) {
                    214:        b = NULL;
                    215:        if (lcp->peer_mrru) {
                    216:            for (k = 0; k < gNumBundles; k++) {
                    217:                if (gBundles[k] && !gBundles[k]->tmpl && gBundles[k]->peer_mrru &&
                    218:                    MpDiscrimEqual(&lcp->peer_discrim, &gBundles[k]->peer_discrim) &&
                    219:                    !strcmp(lcp->auth.params.authname, gBundles[k]->params.authname)) {
                    220:                        break;
                    221:                }
                    222:            }
                    223:            if (k != gNumBundles) {
                    224:                b = gBundles[k];
                    225:            }
                    226:        }
                    227:        if (!b) {
                    228:            const char  *bundt;
                    229:            if (strncmp(l->lcp.auth.params.action, "bundle ", 7) == 0) {
                    230:                bundt = l->lcp.auth.params.action + 7;
                    231:            } else {
                    232:                bundt = LinkMatchAction(l, 3, l->lcp.auth.params.authname);
                    233:            }
                    234:            if (bundt) {
                    235:                if (strcmp(bundt,"##DROP##") == 0) {
                    236:                    /* Action told we must drop this connection */
                    237:                    Log(LG_BUND, ("[%s] Drop link", l->name));
                    238:                    return (0);
                    239:                }
                    240:                if ((bt = BundFind(bundt))) {
                    241:                    if (bt->tmpl) {
                    242:                        Log(LG_BUND, ("[%s] Creating new bundle using template \"%s\".", l->name, bundt));
                    243:                        b = BundInst(bt, NULL, 0, 0);
                    244:                    } else {
                    245:                        b = bt;
                    246:                    }
                    247:                } else {
                    248:                    Log(LG_BUND, ("[%s] Bundle \"%s\" not found.", l->name, bundt));
                    249:                    return (0);
                    250:                }
                    251:            } else {
                    252:                Log(LG_BUND, ("[%s] No bundle specified", l->name));
                    253:                return (0);
                    254:            }
                    255:            if (!b) {
                    256:                Log(LG_BUND, ("[%s] Bundle creation error", l->name));
                    257:                return (0);
                    258:            }
                    259:        }
                    260:        if (b->n_up > 0 &&
                    261:          (b->peer_mrru == 0 || lcp->peer_mrru == 0 || lcp->want_mrru == 0)) {
                    262:            Log(LG_BUND, ("[%s] Can't join bundle %s without "
                    263:                "multilink negotiated.", l->name, b->name));
                    264:            return (0);
                    265:        }
                    266:        if (b->n_up > 0 &&
                    267:          (!MpDiscrimEqual(&lcp->peer_discrim, &b->peer_discrim) ||
                    268:          strcmp(lcp->auth.params.authname, b->params.authname))) {
                    269:            Log(LG_BUND, ("[%s] Can't join bundle %s with different "
                    270:                "peer discriminator/authname.", l->name, b->name));
                    271:            return (0);
                    272:        }
                    273:        k = 0;
                    274:        while (k < NG_PPP_MAX_LINKS && b->links[k] != NULL)
                    275:            k++;
                    276:        if (k < NG_PPP_MAX_LINKS) {
                    277:            l->bund = b;
                    278:            l->bundleIndex = k;
                    279:            b->links[k] = l;
                    280:            b->n_links++;
                    281:        } else {
                    282:            Log(LG_BUND, ("[%s] No more then %d links per bundle allowed. "
                    283:                "Can't join budle.", l->name, NG_PPP_MAX_LINKS));
                    284:            return (0);
                    285:        }
                    286:     }
                    287: 
                    288:     b = l->bund;
                    289: 
                    290:     Log(LG_LINK, ("[%s] Link: Join bundle \"%s\"", l->name, b->name));
                    291: 
                    292:     b->open = TRUE; /* Open bundle on incoming */
                    293: 
                    294:     if (LinkNgJoin(l)) {
                    295:        Log(LG_ERR, ("[%s] Bundle netgraph join failed", l->name));
                    296:        l->bund = NULL;
                    297:        b->links[l->bundleIndex] = NULL;
                    298:        if (!b->stay)
                    299:            BundShutdown(b);
                    300:        return(0);
                    301:     }
                    302:     l->joined_bund = 1;
                    303:     b->n_up++;
                    304: 
                    305:     LinkResetStats(l);
                    306: 
                    307:     if (b->n_up == 1) {
                    308: 
                    309:        /* Cancel re-open timer; we've come up somehow (eg, LCP renegotiation) */
                    310:        TimerStop(&b->reOpenTimer);
                    311: 
                    312:        b->last_up = time(NULL);
                    313: 
                    314:        /* Copy auth params from the first link */
                    315:        authparamsCopy(&l->lcp.auth.params,&b->params);
                    316: 
                    317:        /* Initialize multi-link stuff */
                    318:        if ((b->peer_mrru = lcp->peer_mrru)) {
                    319:            b->peer_discrim = lcp->peer_discrim;
                    320:        }
                    321: 
                    322:        /* Start bandwidth management */
                    323:        BundBmStart(b);
                    324:     }
                    325: 
                    326:     /* Reasses MTU, bandwidth, etc. */
                    327:     BundReasses(b);
                    328: 
                    329:     /* Configure this link */
                    330:     b->pppConfig.links[l->bundleIndex].enableLink = 1;
                    331:     b->pppConfig.links[l->bundleIndex].mru = lcp->peer_mru;
                    332:     b->pppConfig.links[l->bundleIndex].enableACFComp = lcp->peer_acfcomp;
                    333:     b->pppConfig.links[l->bundleIndex].enableProtoComp = lcp->peer_protocomp;
                    334:     b->pppConfig.links[l->bundleIndex].bandwidth =
                    335:        MIN((l->bandwidth / 8 + 5) / 10, NG_PPP_MAX_BANDWIDTH);
                    336:     b->pppConfig.links[l->bundleIndex].latency =
                    337:        MIN((l->latency + 500) / 1000, NG_PPP_MAX_LATENCY);
                    338: 
                    339:     /* What to do when the first link comes up */
                    340:     if (b->n_up == 1) {
                    341: 
                    342:        /* Configure the bundle */
                    343:        b->pppConfig.bund.enableMultilink = (lcp->peer_mrru && lcp->want_mrru)?1:0;
                    344:        /* ng_ppp does not allow MRRU less then 1500 bytes. */
                    345:        b->pppConfig.bund.mrru = (lcp->peer_mrru < 1500) ? 1500 : lcp->peer_mrru;
                    346:        b->pppConfig.bund.xmitShortSeq = lcp->peer_shortseq;
                    347:        b->pppConfig.bund.recvShortSeq = lcp->want_shortseq;
                    348:        b->pppConfig.bund.enableRoundRobin =
                    349:            Enabled(&b->conf.options, BUND_CONF_ROUNDROBIN);
                    350: 
                    351:        /* generate a uniq msession_id */
                    352:        snprintf(b->msession_id, AUTH_MAX_SESSIONID, "%d-%s",
                    353:            (int)(time(NULL) % 10000000), b->name);
                    354:       
                    355:        b->originate = l->originate;
                    356:     }
                    357: 
                    358:     /* Update PPP node configuration */
                    359:     NgFuncSetConfig(b);
                    360: 
                    361:     /* copy msession_id to link */
                    362:     strlcpy(l->msession_id, b->msession_id, sizeof(l->msession_id));
                    363: 
                    364:     /* What to do when the first link comes up */
                    365:     if (b->n_up == 1) {
                    366: 
                    367:        BundNcpsOpen(b);
                    368:        BundNcpsUp(b);
                    369: 
                    370:        BundResetStats(b);
                    371: 
                    372: #ifndef NG_PPP_STATS64    
                    373:        /* starting bundle statistics timer */
                    374:        TimerInit(&b->statsUpdateTimer, "BundUpdateStats", 
                    375:            BUND_STATS_UPDATE_INTERVAL, BundUpdateStatsTimer, b);
                    376:        TimerStartRecurring(&b->statsUpdateTimer);
                    377: #endif
                    378:     }
                    379: 
                    380:     AuthAccountStart(l, AUTH_ACCT_START);
                    381: 
                    382:     return(b->n_up);
                    383: }
                    384: 
                    385: /*
                    386:  * BundLeave()
                    387:  *
                    388:  * This is called when a link leaves the NETWORK phase.
                    389:  */
                    390: 
                    391: void
                    392: BundLeave(Link l)
                    393: {
                    394:     Bund       b = l->bund;
                    395: 
                    396:     /* Elvis has left the bundle */
                    397:     assert(b->n_up > 0);
                    398:   
                    399:     Log(LG_LINK, ("[%s] Link: Leave bundle \"%s\"", l->name, b->name));
                    400: 
                    401:     AuthAccountStart(l, AUTH_ACCT_STOP);
                    402: 
                    403:     /* Disable link */
                    404:     b->pppConfig.links[l->bundleIndex].enableLink = 0;
                    405:     b->pppConfig.links[l->bundleIndex].mru = LCP_DEFAULT_MRU;
                    406:     NgFuncSetConfig(b);
                    407: 
                    408:     LinkNgLeave(l);
                    409:     l->joined_bund = 0;
                    410:     b->n_up--;
                    411:     
                    412:     /* Divorce link and bundle */
                    413:     b->links[l->bundleIndex] = NULL;
                    414:     b->n_links--;
                    415:     l->bund = NULL;
                    416: 
                    417:     BundReasses(b);
                    418:     
                    419:     /* Forget session_ids */
                    420:     l->msession_id[0] = 0;
                    421:   
                    422:     /* Special stuff when last link goes down... */
                    423:     if (b->n_up == 0) {
                    424:   
                    425: #ifndef NG_PPP_STATS64
                    426:        /* stopping bundle statistics timer */
                    427:        TimerStop(&b->statsUpdateTimer);
                    428: #endif
                    429: 
                    430:        /* Reset statistics and auth information */
                    431:        BundBmStop(b);
                    432: 
                    433:        BundNcpsClose(b);
                    434:        BundNcpsDown(b);
                    435:        
                    436: #ifdef USE_NG_BPF
                    437:        IfaceFreeStats(&b->iface.prevstats);
                    438: #endif
                    439: 
                    440:        authparamsDestroy(&b->params);
                    441: 
                    442:        b->msession_id[0] = 0;
                    443:  
                    444:        /* try to open again later */
                    445:        if (b->open && Enabled(&b->conf.options, BUND_CONF_BWMANAGE) &&
                    446:          !Enabled(&b->iface.options, IFACE_CONF_ONDEMAND) && !gShutdownInProgress) {
                    447:            if (b->n_links != 0 || b->conf.linkst[0][0]) {
                    448:                /* wait BUND_REOPEN_DELAY to see if it comes back up */
                    449:                int delay = BUND_REOPEN_DELAY;
                    450:                delay += ((random() ^ gPid ^ time(NULL)) & 1);
                    451:                Log(LG_BUND, ("[%s] Bundle: Last link has gone, reopening in %d seconds", 
                    452:                    b->name, delay));
                    453:                TimerStop(&b->reOpenTimer);
                    454:                TimerInit(&b->reOpenTimer, "BundReOpen",
                    455:                    delay * SECONDS, BundReOpenLinks, b);
                    456:                TimerStart(&b->reOpenTimer);
                    457:                return;
                    458:            } else {
                    459:                Log(LG_BUND, ("[%s] Bundle: Last link has gone, no links for bw-manage defined", 
                    460:                    b->name));
                    461:            }
                    462:        }
                    463:        b->open = FALSE;
                    464:        if (!b->stay)
                    465:            BundShutdown(b);
                    466:     }
                    467: }
                    468: 
                    469: /*
                    470:  * BundReOpenLinks()
                    471:  *
                    472:  * The last link went down, and we waited BUND_REOPEN_DELAY seconds for
                    473:  * it to come back up. It didn't, so close all the links and re-open them
                    474:  * BUND_REOPEN_PAUSE seconds from now.
                    475:  *
                    476:  * The timer calling this is cancelled whenever any link comes up.
                    477:  */
                    478: 
                    479: static void
                    480: BundReOpenLinks(void *arg)
                    481: {
                    482:     Bund b = (Bund)arg;
                    483:     
                    484:     Log(LG_BUND, ("[%s] Bundle: Last link has gone, reopening...", b->name));
                    485:     BundOpenLinks(b);
                    486: }
                    487: 
                    488: /*
                    489:  * BundMsg()
                    490:  *
                    491:  * Deal with incoming message to the bundle
                    492:  */
                    493: 
                    494: static void
                    495: BundMsg(int type, void *arg)
                    496: {
                    497:     Bund       b = (Bund)arg;
                    498: 
                    499:     if (b->dead) {
                    500:        UNREF(b);
                    501:        return;
                    502:     }
                    503:     Log(LG_BUND, ("[%s] Bundle: %s event in state %s",
                    504:        b->name, MsgName(type), b->open ? "OPENED" : "CLOSED"));
                    505:     TimerStop(&b->reOpenTimer);
                    506:     switch (type) {
                    507:     case MSG_OPEN:
                    508:         b->open = TRUE;
                    509:        BundOpenLinks(b);
                    510:         break;
                    511: 
                    512:     case MSG_CLOSE:
                    513:         b->open = FALSE;
                    514:         BundCloseLinks(b);
                    515:         break;
                    516: 
                    517:     default:
                    518:         assert(FALSE);
                    519:     }
                    520:     UNREF(b);
                    521: }
                    522: 
                    523: /*
                    524:  * BundOpenLinks()
                    525:  *
                    526:  * Open one link or all links, depending on whether bandwidth
                    527:  * management is in effect or not.
                    528:  */
                    529: 
                    530: void
                    531: BundOpenLinks(Bund b)
                    532: {
                    533:     int        k;
                    534: 
                    535:     TimerStop(&b->reOpenTimer);
                    536:     if (Enabled(&b->conf.options, BUND_CONF_BWMANAGE)) {
                    537:        if (b->n_links != 0)
                    538:            return;
                    539:        for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                    540:            if (b->links[k]) {
                    541:                BundOpenLink(b->links[k]);
                    542:                break;
                    543:            } else if (b->conf.linkst[k][0]) {
                    544:                BundCreateOpenLink(b, k);
                    545:                break;
                    546:            }
                    547:        }
                    548:     } else {
                    549:        for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                    550:            if (b->links[k])
                    551:                BundOpenLink(b->links[k]);
                    552:            else if (b->conf.linkst[k][0])
                    553:                BundCreateOpenLink(b, k);
                    554:        }
                    555:     }
                    556: }
                    557: 
                    558: /*
                    559:  * BundCreateOpenLink()
                    560:  */
                    561: 
                    562: int
                    563: BundCreateOpenLink(Bund b, int n)
                    564: {
                    565:     if (!b->links[n]) {
                    566:        if (b->conf.linkst[n][0]) {
                    567:            Link l;
                    568:            Link lt = LinkFind(b->conf.linkst[n]);
                    569:            if (!lt) {
                    570:                Log(LG_BUND, ("[%s] Bund: Link \"%s\" not found", b->name, b->conf.linkst[n]));
                    571:                return (-1);
                    572:            }
                    573:            if (PhysIsBusy(lt)) {
                    574:                Log(LG_BUND, ("[%s] Bund: Link \"%s\" is busy", b->name, b->conf.linkst[n]));
                    575:                return (-1);
                    576:            }
                    577:            if (lt->tmpl) {
                    578:                l = LinkInst(lt, NULL, 0, 0);
                    579:            } else
                    580:                l = lt;
                    581:            if (!l) {
                    582:                Log(LG_BUND, ("[%s] Bund: Link \"%s\" creation error", b->name, b->conf.linkst[n]));
                    583:                return (-1);
                    584:            }
                    585:            b->links[n] = l;
                    586:            b->n_links++;
                    587:            l->bund = b;
                    588:            l->bundleIndex = n;
                    589:            l->conf.max_redial = -1;
                    590:        } else {
                    591:            Log(LG_BUND, ("[%s] Bund: Link %d name not specified", b->name, n));
                    592:            return (-1);
                    593:        }
                    594:     }
                    595:     BundOpenLink(b->links[n]);
                    596:     return (0);
                    597: }
                    598: 
                    599: /*
                    600:  * BundOpenLink()
                    601:  */
                    602: 
                    603: void
                    604: BundOpenLink(Link l)
                    605: {
                    606:   Log(LG_BUND, ("[%s] opening link \"%s\"...", l->bund->name, l->name));
                    607:   LinkOpen(l);
                    608: }
                    609: 
                    610: /*
                    611:  * BundCloseLinks()
                    612:  *
                    613:  * Close all links
                    614:  */
                    615: 
                    616: void
                    617: BundCloseLinks(Bund b)
                    618: {
                    619:   int  k;
                    620: 
                    621:   TimerStop(&b->reOpenTimer);
                    622:   for (k = 0; k < NG_PPP_MAX_LINKS; k++)
                    623:     if (b->links[k] && OPEN_STATE(b->links[k]->lcp.fsm.state))
                    624:       BundCloseLink(b->links[k]);
                    625: }
                    626: 
                    627: /*
                    628:  * BundCloseLink()
                    629:  */
                    630: 
                    631: static void
                    632: BundCloseLink(Link l)
                    633: {
                    634:     Log(LG_BUND, ("[%s] Bundle: closing link \"%s\"...", l->bund->name, l->name));
                    635:     LinkClose(l);
                    636: }
                    637: 
                    638: /*
                    639:  * BundNcpsOpen()
                    640:  */
                    641: 
                    642: void
                    643: BundNcpsOpen(Bund b)
                    644: {
                    645:   if (Enabled(&b->conf.options, BUND_CONF_IPCP))
                    646:     IpcpOpen(b);
                    647:   if (Enabled(&b->conf.options, BUND_CONF_IPV6CP))
                    648:     Ipv6cpOpen(b);
                    649:   if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
                    650:     CcpOpen(b);
                    651:   if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
                    652:     EcpOpen(b);
                    653: }
                    654: 
                    655: /*
                    656:  * BundNcpsUp()
                    657:  */
                    658: 
                    659: static void
                    660: BundNcpsUp(Bund b)
                    661: {
                    662:   if (Enabled(&b->conf.options, BUND_CONF_IPCP))
                    663:     IpcpUp(b);
                    664:   if (Enabled(&b->conf.options, BUND_CONF_IPV6CP))
                    665:     Ipv6cpUp(b);
                    666:   if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
                    667:     CcpUp(b);
                    668:   if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
                    669:     EcpUp(b);
                    670: }
                    671: 
                    672: void
                    673: BundNcpsStart(Bund b, int proto)
                    674: {
                    675:     b->ncpstarted |= ((1<<proto)>>1);
                    676: }
                    677: 
                    678: void
                    679: BundNcpsFinish(Bund b, int proto)
                    680: {
                    681:     b->ncpstarted &= (~((1<<proto)>>1));
                    682:     if (!b->ncpstarted) {
                    683:        Log(LG_BUND, ("[%s] Bundle: No NCPs left. Closing links...", b->name));
                    684:        RecordLinkUpDownReason(b, NULL, 0, STR_PROTO_ERR, NULL);
                    685:        BundCloseLinks(b); /* We have nothing to live for */
                    686:     }
                    687: }
                    688: 
                    689: void
                    690: BundNcpsJoin(Bund b, int proto)
                    691: {
                    692:        IfaceState      iface = &b->iface;
                    693: 
                    694:        if (iface->dod) {
                    695:                if (iface->ip_up) {
                    696:                        iface->ip_up = 0;
                    697:                        IfaceIpIfaceDown(b);
                    698:                }
                    699:                if (iface->ipv6_up) {
                    700:                        iface->ipv6_up = 0;
                    701:                        IfaceIpv6IfaceDown(b);
                    702:                }
                    703:                iface->dod = 0;
                    704:                iface->up = 0;
                    705:                IfaceDown(b);
                    706:        }
                    707:     
                    708:        switch(proto) {
                    709:        case NCP_IPCP:
                    710:                if (!iface->ip_up) {
                    711:                        iface->ip_up = 1;
                    712:                        if (IfaceIpIfaceUp(b, 1)) {
                    713:                            iface->ip_up = 0;
                    714:                            return;
                    715:                        };
                    716:                }
                    717:                break;
                    718:        case NCP_IPV6CP:
                    719:                if (!iface->ipv6_up) {
                    720:                        iface->ipv6_up = 1;
                    721:                        if (IfaceIpv6IfaceUp(b, 1)) {
                    722:                            iface->ipv6_up = 0;
                    723:                            return;
                    724:                        };
                    725:                }
                    726:                break;
                    727:        case NCP_NONE: /* Manual call by 'open iface' */
                    728:                if (Enabled(&b->conf.options, BUND_CONF_IPCP) &&
                    729:                    !iface->ip_up) {
                    730:                        iface->ip_up = 1;
                    731:                        if (IfaceIpIfaceUp(b, 0)) {
                    732:                            iface->ip_up = 0;
                    733:                            return;
                    734:                        };
                    735:                }
                    736:                if (Enabled(&b->conf.options, BUND_CONF_IPV6CP) &&
                    737:                    !iface->ipv6_up) {
                    738:                        iface->ipv6_up = 1;
                    739:                        if (IfaceIpv6IfaceUp(b, 0)) {
                    740:                            iface->ipv6_up = 0;
                    741:                            return;
                    742:                        };
                    743:                }
                    744:                break;
                    745:        }
                    746: 
                    747:        if (!iface->up) {
                    748:                iface->up = 1;
                    749:                if (proto == NCP_NONE) {
                    750:                        iface->dod = 1;
                    751:                        IfaceUp(b, 0);
                    752:                } else {
                    753:                        IfaceUp(b, 1);
                    754:                }
                    755:        }
                    756: }
                    757: 
                    758: void
                    759: BundNcpsLeave(Bund b, int proto)
                    760: {
                    761:        IfaceState      iface = &b->iface;
                    762:        switch(proto) {
                    763:        case NCP_IPCP:
                    764:                if (iface->ip_up) {
                    765:                        iface->ip_up=0;
                    766:                        IfaceIpIfaceDown(b);
                    767:                }
                    768:                break;
                    769:        case NCP_IPV6CP:
                    770:                if (iface->ipv6_up) {
                    771:                        iface->ipv6_up=0;
                    772:                        IfaceIpv6IfaceDown(b);
                    773:                }
                    774:                break;
                    775:        case NCP_NONE:
                    776:                if (iface->ip_up) {
                    777:                        iface->ip_up=0;
                    778:                        IfaceIpIfaceDown(b);
                    779:                }
                    780:                if (iface->ipv6_up) {
                    781:                        iface->ipv6_up=0;
                    782:                        IfaceIpv6IfaceDown(b);
                    783:                }
                    784:                break;
                    785:        }
                    786:     
                    787:        if ((iface->up) && (!iface->ip_up) && (!iface->ipv6_up)) {
                    788:                iface->dod=0;
                    789:                iface->up=0;
                    790:                IfaceDown(b);
                    791:                if (iface->open) {
                    792:                        if (Enabled(&b->conf.options, BUND_CONF_IPCP)) {
                    793:                                iface->ip_up=1;
                    794:                                if (IfaceIpIfaceUp(b, 0))
                    795:                                    iface->ip_up = 0;
                    796:                        }
                    797:                        if (Enabled(&b->conf.options, BUND_CONF_IPV6CP)) {
                    798:                                iface->ipv6_up=1;
                    799:                                if (IfaceIpv6IfaceUp(b, 0))
                    800:                                    iface->ipv6_up = 0;
                    801:                        }
                    802:                        if (iface->ip_up || iface->ipv6_up) {
                    803:                            iface->dod=1;
                    804:                            iface->up=1;
                    805:                            IfaceUp(b, 0);
                    806:                        }
                    807:                }
                    808:        }
                    809: }
                    810: 
                    811: /*
                    812:  * BundNcpsDown()
                    813:  */
                    814: 
                    815: static void
                    816: BundNcpsDown(Bund b)
                    817: {
                    818:   if (Enabled(&b->conf.options, BUND_CONF_IPCP))
                    819:     IpcpDown(b);
                    820:   if (Enabled(&b->conf.options, BUND_CONF_IPV6CP))
                    821:     Ipv6cpDown(b);
                    822:   if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
                    823:     CcpDown(b);
                    824:   if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
                    825:     EcpDown(b);
                    826: }
                    827: 
                    828: /*
                    829:  * BundNcpsClose()
                    830:  */
                    831: 
                    832: void
                    833: BundNcpsClose(Bund b)
                    834: {
                    835:   if (Enabled(&b->conf.options, BUND_CONF_IPCP))
                    836:     IpcpClose(b);
                    837:   if (Enabled(&b->conf.options, BUND_CONF_IPV6CP))
                    838:     Ipv6cpClose(b);
                    839:   if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
                    840:     CcpClose(b);
                    841:   if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
                    842:     EcpClose(b);
                    843: }
                    844: 
                    845: /*
                    846:  * BundReasses()
                    847:  *
                    848:  * Here we do a reassessment of things after a new link has been
                    849:  * added to or removed from the bundle.
                    850:  */
                    851: 
                    852: static void
                    853: BundReasses(Bund b)
                    854: {
                    855:   BundBm       const bm = &b->bm;
                    856: 
                    857:   /* Update system interface parameters */
                    858:   BundUpdateParams(b);
                    859: 
                    860:   Log(LG_BUND, ("[%s] Bundle: Status update: up %d link%s, total bandwidth %d bps",
                    861:     b->name, b->n_up, b->n_up == 1 ? "" : "s", bm->total_bw));
                    862: 
                    863: }
                    864: 
                    865: /*
                    866:  * BundUpdateParams()
                    867:  *
                    868:  * Recalculate interface MTU and bandwidth.
                    869:  */
                    870: 
                    871: void
                    872: BundUpdateParams(Bund b)
                    873: {
                    874:   BundBm       const bm = &b->bm;
                    875:   int          k, mtu, the_link = 0;
                    876: 
                    877:     /* Recalculate how much bandwidth we have */
                    878:     bm->total_bw = 0;
                    879:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                    880:        if (b->links[k] && b->links[k]->lcp.phase == PHASE_NETWORK) {
                    881:            bm->total_bw += b->links[k]->bandwidth;
                    882:            the_link = k;
                    883:        }
                    884:     }
                    885:     if (bm->total_bw < BUND_MIN_TOT_BW)
                    886:        bm->total_bw = BUND_MIN_TOT_BW;
                    887: 
                    888:     /* Recalculate MTU corresponding to peer's MRU */
                    889:     if (b->n_up == 0) {
                    890:         mtu = NG_IFACE_MTU_DEFAULT;    /* Reset to default settings */
                    891: 
                    892:     } else if (!b->peer_mrru) {                /* If no multilink, use peer MRU */
                    893:        mtu = MIN(b->links[the_link]->lcp.peer_mru,
                    894:                  b->links[the_link]->type->mtu);
                    895: 
                    896:     } else {           /* Multilink, use peer MRRU */
                    897:         mtu = MIN(b->peer_mrru, MP_MAX_MRRU);
                    898:     }
                    899: 
                    900:     /* Subtract to make room for various frame-bloating protocols */
                    901:     if (b->n_up > 0) {
                    902:        if (Enabled(&b->conf.options, BUND_CONF_COMPRESSION))
                    903:            mtu = CcpSubtractBloat(b, mtu);
                    904:        if (Enabled(&b->conf.options, BUND_CONF_ENCRYPTION))
                    905:            mtu = EcpSubtractBloat(b, mtu);
                    906:     }
                    907: 
                    908:     /* Update interface MTU */
                    909:     IfaceSetMTU(b, mtu);
                    910:  
                    911: }
                    912: 
                    913: /*
                    914:  * BundCommand()
                    915:  *
                    916:  * Show list of all bundles or set bundle
                    917:  */
                    918: 
                    919: int
                    920: BundCommand(Context ctx, int ac, char *av[], void *arg)
                    921: {
                    922:     Bund       sb;
                    923:     int                j, k;
                    924: 
                    925:     if (ac > 1)
                    926:        return (-1);
                    927: 
                    928:     if (ac == 0) {
                    929:        Printf("Defined bundles:\r\n");
                    930:        for (k = 0; k < gNumBundles; k++) {
                    931:            if ((sb = gBundles[k]) != NULL) {
                    932:                Printf("\t%-15s", sb->name);
                    933:                for (j = 0; j < NG_PPP_MAX_LINKS; j++) {
                    934:                    if (sb->links[j])
                    935:                        Printf("%s ", sb->links[j]->name);
                    936:                }
                    937:                Printf("\r\n");
                    938:            }
                    939:        }
                    940:        return (0);
                    941:     }
                    942: 
                    943:     if ((sb = BundFind(av[0])) == NULL) {
                    944:         RESETREF(ctx->lnk, NULL);
                    945:        RESETREF(ctx->bund, NULL);
                    946:        RESETREF(ctx->rep, NULL);
                    947:         Error("Bundle \"%s\" not defined.", av[0]);
                    948:     }
                    949: 
                    950:     /* Change bundle, and link also if needed */
                    951:     RESETREF(ctx->bund, sb);
                    952:     if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
                    953:         RESETREF(ctx->lnk, ctx->bund->links[0]);
                    954:     }
                    955:     RESETREF(ctx->rep, NULL);
                    956:     return(0);
                    957: }
                    958: 
                    959: /*
                    960:  * MSessionCommand()
                    961:  */
                    962: 
                    963: int
                    964: MSessionCommand(Context ctx, int ac, char *av[], void *arg)
                    965: {
                    966:     int                k;
                    967: 
                    968:     if (ac > 1)
                    969:        return (-1);
                    970: 
                    971:     if (ac == 0) {
                    972:        Printf("Present msessions:\r\n");
                    973:        for (k = 0; k < gNumBundles; k++) {
                    974:            if (gBundles[k] && gBundles[k]->msession_id[0])
                    975:                Printf("\t%s\r\n", gBundles[k]->msession_id);
                    976:        }
                    977:        return (0);
                    978:     }
                    979: 
                    980:     /* Find bundle */
                    981:     for (k = 0;
                    982:        k < gNumBundles && (gBundles[k] == NULL || 
                    983:            strcmp(gBundles[k]->msession_id, av[0]));
                    984:        k++);
                    985:     if (k == gNumBundles) {
                    986:        /* Change default link and bundle */
                    987:        RESETREF(ctx->lnk, NULL);
                    988:        RESETREF(ctx->bund, NULL);
                    989:        RESETREF(ctx->rep, NULL);
                    990:        Error("msession \"%s\" is not found", av[0]);
                    991:     }
                    992: 
                    993:     /* Change default link and bundle */
                    994:     RESETREF(ctx->bund, gBundles[k]);
                    995:     if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
                    996:         RESETREF(ctx->lnk, ctx->bund->links[0]);
                    997:     }
                    998:     RESETREF(ctx->rep, NULL);
                    999: 
                   1000:     return(0);
                   1001: }
                   1002: 
                   1003: /*
                   1004:  * IfaceCommand()
                   1005:  */
                   1006: 
                   1007: int
                   1008: IfaceCommand(Context ctx, int ac, char *av[], void *arg)
                   1009: {
                   1010:     int                k;
                   1011: 
                   1012:     if (ac > 1)
                   1013:        return (-1);
                   1014: 
                   1015:     if (ac == 0) {
                   1016:        Printf("Present ifaces:\r\n");
                   1017:        for (k = 0; k < gNumBundles; k++) {
                   1018:            if (gBundles[k] && gBundles[k]->iface.ifname[0])
                   1019:                Printf("\t%s\t%s\r\n", gBundles[k]->iface.ifname, gBundles[k]->name);
                   1020:        }
                   1021:        return (0);
                   1022:     }
                   1023: 
                   1024:     /* Find bundle */
                   1025:     for (k = 0;
                   1026:        k < gNumBundles && (gBundles[k] == NULL || 
                   1027:            strcmp(gBundles[k]->iface.ifname, av[0]));
                   1028:        k++);
                   1029:     if (k == gNumBundles) {
                   1030:        /* Change default link and bundle */
                   1031:        RESETREF(ctx->lnk, NULL);
                   1032:        RESETREF(ctx->bund, NULL);
                   1033:        RESETREF(ctx->rep, NULL);
                   1034:        Error("iface \"%s\" is not found", av[0]);
                   1035:     }
                   1036: 
                   1037:     /* Change default link and bundle */
                   1038:     RESETREF(ctx->bund, gBundles[k]);
                   1039:     if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
                   1040:         RESETREF(ctx->lnk, ctx->bund->links[0]);
                   1041:     }
                   1042:     RESETREF(ctx->rep, NULL);
                   1043: 
                   1044:     return(0);
                   1045: }
                   1046: 
                   1047: /*
                   1048:  * BundCreate()
                   1049:  */
                   1050: 
                   1051: int
                   1052: BundCreate(Context ctx, int ac, char *av[], void *arg)
                   1053: {
                   1054:     Bund       b, bt = NULL;
                   1055:     u_char     tmpl = 0;
                   1056:     u_char     stay = 0;
                   1057:     int        k;
                   1058: 
                   1059:     RESETREF(ctx->lnk, NULL);
                   1060:     RESETREF(ctx->bund, NULL);
                   1061:     RESETREF(ctx->rep, NULL);
                   1062: 
                   1063:     if (ac < 1)
                   1064:        return(-1);
                   1065: 
                   1066:     if (strcmp(av[0], "template") == 0) {
                   1067:        tmpl = 1;
                   1068:        stay = 1;
                   1069:     } else if (strcmp(av[0], "static") == 0)
                   1070:        stay = 1;
                   1071: 
                   1072:     if (ac - stay < 1 || ac - stay > 2)
                   1073:        return(-1);
                   1074: 
                   1075:     if (strlen(av[0 + stay]) >= (LINK_MAX_NAME - tmpl * (IFNUMLEN + 1)))
                   1076:        Error("Bundle name \"%s\" is too long", av[0 + stay]);
                   1077: 
                   1078:     /* See if bundle name already taken */
                   1079:     if ((b = BundFind(av[0 + stay])) != NULL)
                   1080:        Error("Bundle \"%s\" already exists", av[0 + stay]);
                   1081: 
                   1082:     if (ac - stay == 2) {
                   1083:        /* See if template name specified */
                   1084:        if ((bt = BundFind(av[1 + stay])) == NULL)
                   1085:            Error("Bundle template \"%s\" not found", av[1 + stay]);
                   1086:        if (!bt->tmpl)
                   1087:            Error("Bundle \"%s\" is not a template", av[1 + stay]);
                   1088:     }
                   1089: 
                   1090:     if (bt) {
                   1091:        b = BundInst(bt, av[0 + stay], tmpl, stay);
                   1092:     } else {
                   1093:        /* Create a new bundle structure */
                   1094:        b = Malloc(MB_BUND, sizeof(*b));
                   1095:        strlcpy(b->name, av[0 + stay], sizeof(b->name));
                   1096:        b->tmpl = tmpl;
                   1097:        b->stay = stay;
                   1098: 
                   1099:        /* Add bundle to the list of bundles and make it the current active bundle */
                   1100:        for (k = 0; k < gNumBundles && gBundles[k] != NULL; k++);
                   1101:        if (k == gNumBundles)                   /* add a new bundle pointer */
                   1102:            LengthenArray(&gBundles, sizeof(*gBundles), &gNumBundles, MB_BUND);
                   1103: 
                   1104:        b->id = k;
                   1105:        gBundles[k] = b;
                   1106:        REF(b);
                   1107: 
                   1108:        /* Get message channel */
                   1109:        MsgRegister(&b->msgs, BundMsg);
                   1110: 
                   1111:        /* Initialize bundle configuration */
                   1112:        b->conf.retry_timeout = BUND_DEFAULT_RETRY;
                   1113:        b->conf.bm_S = BUND_BM_DFL_S;
                   1114:        b->conf.bm_Hi = BUND_BM_DFL_Hi;
                   1115:        b->conf.bm_Lo = BUND_BM_DFL_Lo;
                   1116:        b->conf.bm_Mc = BUND_BM_DFL_Mc;
                   1117:        b->conf.bm_Md = BUND_BM_DFL_Md;
                   1118: 
                   1119:        Enable(&b->conf.options, BUND_CONF_IPCP);
                   1120:        Disable(&b->conf.options, BUND_CONF_IPV6CP);
                   1121: 
                   1122:        Disable(&b->conf.options, BUND_CONF_BWMANAGE);
                   1123:        Disable(&b->conf.options, BUND_CONF_COMPRESSION);
                   1124:        Disable(&b->conf.options, BUND_CONF_ENCRYPTION);
                   1125:         Disable(&b->conf.options, BUND_CONF_CRYPT_REQD);
                   1126:   
                   1127:         /* Init iface and NCP's */
                   1128:        IfaceInit(b);
                   1129:         IpcpInit(b);
                   1130:         Ipv6cpInit(b);
                   1131:         CcpInit(b);
                   1132:         EcpInit(b);
                   1133: 
                   1134:        if (!tmpl) {
                   1135:            /* Setup netgraph stuff */
                   1136:            if (BundNgInit(b) < 0) {
                   1137:                gBundles[b->id] = NULL;
                   1138:                Freee(b);
                   1139:                Error("Bundle netgraph initialization failed");
                   1140:            }
                   1141:        }
                   1142:     }
                   1143:   
                   1144:     RESETREF(ctx->bund, b);
                   1145:   
                   1146:     /* Done */
                   1147:     return(0);
                   1148: }
                   1149: 
                   1150: /*
                   1151:  * BundDestroy()
                   1152:  */
                   1153: 
                   1154: int
                   1155: BundDestroy(Context ctx, int ac, char *av[], void *arg)
                   1156: {
                   1157:     Bund       b;
                   1158: 
                   1159:     if (ac > 1)
                   1160:        return(-1);
                   1161: 
                   1162:     if (ac == 1) {
                   1163:        if ((b = BundFind(av[0])) == NULL)
                   1164:            Error("Bund \"%s\" not found", av[0]);
                   1165:     } else {
                   1166:        if (ctx->bund) {
                   1167:            b = ctx->bund;
                   1168:        } else
                   1169:            Error("No bundle selected to destroy");
                   1170:     }
                   1171:     
                   1172:     if (b->tmpl) {
                   1173:        b->tmpl = 0;
                   1174:        b->stay = 0;
                   1175:        BundShutdown(b);
                   1176:     } else {
                   1177:        b->stay = 0;
                   1178:        if (b->n_up) {
                   1179:            BundClose(b);
                   1180:        } else {
                   1181:            BundShutdown(b);
                   1182:        }
                   1183:     }
                   1184: 
                   1185:     return (0);
                   1186: }
                   1187: 
                   1188: /*
                   1189:  * BundInst()
                   1190:  */
                   1191: 
                   1192: Bund
                   1193: BundInst(Bund bt, char *name, int tmpl, int stay)
                   1194: {
                   1195:     Bund       b;
                   1196:     int        k;
                   1197: 
                   1198:     /* Create a new bundle structure */
                   1199:     b = Mdup(MB_BUND, bt, sizeof(*b));
                   1200:     b->tmpl = tmpl;
                   1201:     b->stay = stay;
                   1202:     b->refs = 0;
                   1203: 
                   1204:     /* Add bundle to the list of bundles and make it the current active bundle */
                   1205:     for (k = 0; k < gNumBundles && gBundles[k] != NULL; k++);
                   1206:     if (k == gNumBundles)                      /* add a new bundle pointer */
                   1207:        LengthenArray(&gBundles, sizeof(*gBundles), &gNumBundles, MB_BUND);
                   1208: 
                   1209:     b->id = k;
                   1210:     if (name)
                   1211:        strlcpy(b->name, name, sizeof(b->name));
                   1212:     else
                   1213:        snprintf(b->name, sizeof(b->name), "%s-%d", bt->name, k);
                   1214:     gBundles[k] = b;
                   1215:     REF(b);
                   1216: 
                   1217:     /* Inst iface and NCP's */
                   1218:     IfaceInst(b, bt);
                   1219:     IpcpInst(b, bt);
                   1220:     Ipv6cpInst(b, bt);
                   1221:     CcpInst(b, bt);
                   1222:     EcpInst(b, bt);
                   1223: 
                   1224:     if (!tmpl) {
                   1225:        /* Setup netgraph stuff */
                   1226:        if (BundNgInit(b) < 0) {
                   1227:            Log(LG_ERR, ("[%s] Bundle netgraph initialization failed", b->name));
                   1228:            gBundles[b->id] = NULL;
                   1229:            Freee(b);
                   1230:            return(0);
                   1231:        }
                   1232:     }
                   1233: 
                   1234:     return (b);
                   1235: }
                   1236: 
                   1237: /*
                   1238:  * BundShutdown()
                   1239:  *
                   1240:  * Shutdown the netgraph stuff associated with bundle
                   1241:  */
                   1242: 
                   1243: void
                   1244: BundShutdown(Bund b)
                   1245: {
                   1246:     Link       l;
                   1247:     int                k;
                   1248: 
                   1249:     Log(LG_BUND, ("[%s] Bundle: Shutdown", b->name));
                   1250:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1251:        if ((l = b->links[k]) != NULL) {
                   1252:            if (!l->stay)
                   1253:                LinkShutdown(l);
                   1254:            else {
                   1255:                l->bund = NULL;
                   1256:                b->links[k] = NULL;
                   1257:            }
                   1258:        }
                   1259:     }
                   1260: 
                   1261:     if (b->hook[0])
                   1262:        BundNgShutdown(b, 1, 1);
                   1263:     gBundles[b->id] = NULL;
                   1264:     MsgUnRegister(&b->msgs);
                   1265:     b->dead = 1;
                   1266:     IfaceDestroy(b);
                   1267:     UNREF(b);
                   1268: }
                   1269: 
                   1270: /*
                   1271:  * BundStat()
                   1272:  *
                   1273:  * Show state of a bundle
                   1274:  */
                   1275: 
                   1276: int
                   1277: BundStat(Context ctx, int ac, char *av[], void *arg)
                   1278: {
                   1279:   Bund sb;
                   1280:   int  k, bw, tbw, nup;
                   1281:   char buf[64];
                   1282: 
                   1283:   /* Find bundle they're talking about */
                   1284:   switch (ac) {
                   1285:     case 0:
                   1286:       sb = ctx->bund;
                   1287:       break;
                   1288:     case 1:
                   1289:       if ((sb = BundFind(av[0])) == NULL)
                   1290:        Error("Bundle \"%s\" not defined", av[0]);
                   1291:       break;
                   1292:     default:
                   1293:       return(-1);
                   1294:   }
                   1295: 
                   1296:   /* Show stuff about the bundle */
                   1297:   for (tbw = bw = nup = k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1298:     if (sb->links[k]) {
                   1299:        if (sb->links[k]->lcp.phase == PHASE_NETWORK) {
                   1300:            nup++;
                   1301:            bw += sb->links[k]->bandwidth;
                   1302:        }
                   1303:        tbw += sb->links[k]->bandwidth;
                   1304:     }
                   1305:   }
                   1306: 
                   1307:   Printf("Bundle '%s'%s:\r\n", sb->name, sb->tmpl?" (template)":(sb->stay?" (static)":""));
                   1308:   Printf("\tLinks          : ");
                   1309:   BundShowLinks(ctx, sb);
                   1310:   Printf("\tStatus         : %s\r\n", sb->open ? "OPEN" : "CLOSED");
                   1311:   if (sb->n_up)
                   1312:     Printf("\tSession time   : %ld seconds\r\n", (long int)(time(NULL) - sb->last_up));
                   1313:   Printf("\tMultiSession Id: %s\r\n", sb->msession_id);
                   1314:   Printf("\tTotal bandwidth: %u bits/sec\r\n", tbw);
                   1315:   Printf("\tAvail bandwidth: %u bits/sec\r\n", bw);
                   1316:   Printf("\tPeer authname  : \"%s\"\r\n", sb->params.authname);
                   1317: 
                   1318:   /* Show configuration */
                   1319:   Printf("Configuration:\r\n");
                   1320:   Printf("\tRetry timeout  : %d seconds\r\n", sb->conf.retry_timeout);
                   1321:   Printf("\tBW-manage:\r\n");
                   1322:   Printf("\t  Period       : %d seconds\r\n", sb->conf.bm_S);
                   1323:   Printf("\t  Low mark     : %d%%\r\n", sb->conf.bm_Lo);
                   1324:   Printf("\t  High mark    : %d%%\r\n", sb->conf.bm_Hi);
                   1325:   Printf("\t  Min conn     : %d seconds\r\n", sb->conf.bm_Mc);
                   1326:   Printf("\t  Min disc     : %d seconds\r\n", sb->conf.bm_Md);
                   1327:   Printf("\t  Links        : ");
                   1328:   for (k = 0; k < NG_PPP_MAX_LINKS; k++)
                   1329:     Printf("%s ", sb->conf.linkst[k]);
                   1330:   Printf("\r\n");
                   1331:   Printf("Bundle level options:\r\n");
                   1332:   OptStat(ctx, &sb->conf.options, gConfList);
                   1333: 
                   1334:     /* Show peer info */
                   1335:     Printf("Multilink PPP:\r\n");
                   1336:     Printf("\tStatus         : %s\r\n",
                   1337:        sb->peer_mrru ? "Active" : "Inactive");
                   1338:     if (sb->peer_mrru) {
                   1339:       Printf("\tPeer MRRU      : %d bytes\r\n", sb->peer_mrru);
                   1340:       Printf("\tPeer auth name : \"%s\"\r\n", sb->params.authname);
                   1341:       Printf("\tPeer discrimin.: %s\r\n", MpDiscrimText(&sb->peer_discrim, buf, sizeof(buf)));
                   1342:     }
                   1343: 
                   1344:     if (!sb->tmpl) {
                   1345:        /* Show stats */
                   1346:        BundUpdateStats(sb);
                   1347:        Printf("Traffic stats:\r\n");
                   1348: 
                   1349:        Printf("\tInput octets   : %llu\r\n", (unsigned long long)sb->stats.recvOctets);
                   1350:        Printf("\tInput frames   : %llu\r\n", (unsigned long long)sb->stats.recvFrames);
                   1351:        Printf("\tOutput octets  : %llu\r\n", (unsigned long long)sb->stats.xmitOctets);
                   1352:        Printf("\tOutput frames  : %llu\r\n", (unsigned long long)sb->stats.xmitFrames);
                   1353:        Printf("\tBad protocols  : %llu\r\n", (unsigned long long)sb->stats.badProtos);
                   1354:        Printf("\tRunts          : %llu\r\n", (unsigned long long)sb->stats.runts);
                   1355:        Printf("\tDup fragments  : %llu\r\n", (unsigned long long)sb->stats.dupFragments);
                   1356:        Printf("\tDrop fragments : %llu\r\n", (unsigned long long)sb->stats.dropFragments);
                   1357:     }
                   1358: 
                   1359:     return(0);
                   1360: }
                   1361: 
                   1362: /* 
                   1363:  * BundUpdateStats()
                   1364:  */
                   1365: 
                   1366: void
                   1367: BundUpdateStats(Bund b)
                   1368: {
                   1369: #ifndef NG_PPP_STATS64
                   1370:   struct ng_ppp_link_stat      stats;
                   1371: #endif
                   1372:   int  l = NG_PPP_BUNDLE_LINKNUM;
                   1373: 
                   1374: #if (__FreeBSD_version < 602104 || (__FreeBSD_version >= 700000 && __FreeBSD_version < 700029))
                   1375:   /* Workaround for broken ng_ppp bundle stats */
                   1376:   if (!b->peer_mrru)
                   1377:     l = 0;
                   1378: #endif
                   1379: 
                   1380: #ifndef NG_PPP_STATS64
                   1381:   if (NgFuncGetStats(b, l, &stats) != -1) {
                   1382:     b->stats.xmitFrames += abs(stats.xmitFrames - b->oldStats.xmitFrames);
                   1383:     b->stats.xmitOctets += abs(stats.xmitOctets - b->oldStats.xmitOctets);
                   1384:     b->stats.recvFrames += abs(stats.recvFrames - b->oldStats.recvFrames);
                   1385:     b->stats.recvOctets += abs(stats.recvOctets - b->oldStats.recvOctets);
                   1386:     b->stats.badProtos  += abs(stats.badProtos - b->oldStats.badProtos);
                   1387:     b->stats.runts       += abs(stats.runts - b->oldStats.runts);
                   1388:     b->stats.dupFragments += abs(stats.dupFragments - b->oldStats.dupFragments);
                   1389:     b->stats.dropFragments += abs(stats.dropFragments - b->oldStats.dropFragments);
                   1390:   }
                   1391: 
                   1392:   b->oldStats = stats;
                   1393: #else
                   1394:     NgFuncGetStats64(b, l, &b->stats);
                   1395: #endif
                   1396: }
                   1397: 
                   1398: /* 
                   1399:  * BundUpdateStatsTimer()
                   1400:  */
                   1401: 
                   1402: void
                   1403: BundUpdateStatsTimer(void *cookie)
                   1404: {
                   1405:     Bund       b = (Bund)cookie;
                   1406:     int                k;
                   1407:   
                   1408:     BundUpdateStats(b);
                   1409:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1410:        if (b->links[k] && b->links[k]->joined_bund)
                   1411:            LinkUpdateStats(b->links[k]);
                   1412:     }
                   1413: }
                   1414: 
                   1415: /*
                   1416:  * BundResetStats()
                   1417:  */
                   1418: 
                   1419: void
                   1420: BundResetStats(Bund b)
                   1421: {
                   1422:   NgFuncClrStats(b, NG_PPP_BUNDLE_LINKNUM);
                   1423:   memset(&b->stats, 0, sizeof(b->stats));
                   1424: #ifndef NG_PPP_STATS64
                   1425:   memset(&b->oldStats, 0, sizeof(b->oldStats));
                   1426: #endif
                   1427: }
                   1428: 
                   1429: /*
                   1430:  * BundShowLinks()
                   1431:  */
                   1432: 
                   1433: void
                   1434: BundShowLinks(Context ctx, Bund sb)
                   1435: {
                   1436:     int                j;
                   1437: 
                   1438:     for (j = 0; j < NG_PPP_MAX_LINKS; j++) {
                   1439:        if (sb->links[j]) {
                   1440:            Printf("%s[%s/%s] ", sb->links[j]->name,
                   1441:                FsmStateName(sb->links[j]->lcp.fsm.state),
                   1442:                gPhysStateNames[sb->links[j]->state]);
                   1443:        }
                   1444:     }
                   1445:     Printf("\r\n");
                   1446: }
                   1447: 
                   1448: /*
                   1449:  * BundFind()
                   1450:  *
                   1451:  * Find a bundle structure
                   1452:  */
                   1453: 
                   1454: Bund
                   1455: BundFind(const char *name)
                   1456: {
                   1457:   int  k;
                   1458: 
                   1459:   for (k = 0;
                   1460:     k < gNumBundles && (!gBundles[k] || strcmp(gBundles[k]->name, name));
                   1461:     k++);
                   1462:   return((k < gNumBundles) ? gBundles[k] : NULL);
                   1463: }
                   1464: 
                   1465: /*
                   1466:  * BundBmStart()
                   1467:  *
                   1468:  * Start bandwidth management timer
                   1469:  */
                   1470: 
                   1471: static void
                   1472: BundBmStart(Bund b)
                   1473: {
                   1474:     int        k;
                   1475: 
                   1476:     /* Reset bandwidth management stats */
                   1477:     memset(&b->bm.traffic, 0, sizeof(b->bm.traffic));
                   1478:     memset(&b->bm.avail, 0, sizeof(b->bm.avail));
                   1479:     memset(&b->bm.wasUp, 0, sizeof(b->bm.wasUp));
                   1480:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1481:        if (b->links[k]) {
                   1482:            memset(&b->links[k]->bm.idleStats,
                   1483:                0, sizeof(b->links[k]->bm.idleStats));
                   1484:        }
                   1485:     }
                   1486: 
                   1487:   /* Start bandwidth management timer */
                   1488:   TimerStop(&b->bm.bmTimer);
                   1489:   if (Enabled(&b->conf.options, BUND_CONF_BWMANAGE)) {
                   1490:     TimerInit(&b->bm.bmTimer, "BundBm",
                   1491:       (b->conf.bm_S * SECONDS) / BUND_BM_N,
                   1492:       BundBmTimeout, b);
                   1493:     TimerStart(&b->bm.bmTimer);
                   1494:   }
                   1495: }
                   1496: 
                   1497: /*
                   1498:  * BundBmStop()
                   1499:  */
                   1500: 
                   1501: static void
                   1502: BundBmStop(Bund b)
                   1503: {
                   1504:   TimerStop(&b->bm.bmTimer);
                   1505: }
                   1506: 
                   1507: /*
                   1508:  * BundBmTimeout()
                   1509:  *
                   1510:  * Do a bandwidth management update
                   1511:  */
                   1512: 
                   1513: static void
                   1514: BundBmTimeout(void *arg)
                   1515: {
                   1516:     Bund               b = (Bund)arg;
                   1517: 
                   1518:     const time_t       now = time(NULL);
                   1519:     u_int              availTotal;
                   1520:     u_int              inUtilTotal = 0, outUtilTotal = 0;
                   1521:     u_int              inBitsTotal, outBitsTotal;
                   1522:     u_int              inUtil[BUND_BM_N];      /* Incoming % utilization */
                   1523:     u_int              outUtil[BUND_BM_N];     /* Outgoing % utilization */
                   1524:     int                        j, k;
                   1525: 
                   1526:     /* Shift and update stats */
                   1527:     memmove(&b->bm.wasUp[1], &b->bm.wasUp[0],
                   1528:        (BUND_BM_N - 1) * sizeof(b->bm.wasUp[0]));
                   1529:     b->bm.wasUp[0] = b->n_up;
                   1530:     memmove(&b->bm.avail[1], &b->bm.avail[0],
                   1531:        (BUND_BM_N - 1) * sizeof(b->bm.avail[0]));
                   1532:     b->bm.avail[0] = b->bm.total_bw;
                   1533: 
                   1534:     /* Shift stats */
                   1535:     memmove(&b->bm.traffic[0][1], &b->bm.traffic[0][0],
                   1536:        (BUND_BM_N - 1) * sizeof(b->bm.traffic[0][0]));
                   1537:     memmove(&b->bm.traffic[1][1], &b->bm.traffic[1][0],
                   1538:        (BUND_BM_N - 1) * sizeof(b->bm.traffic[1][0]));
                   1539:     b->bm.traffic[0][0] = 0;
                   1540:     b->bm.traffic[1][0] = 0;
                   1541:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1542:        if (b->links[k] && b->links[k]->joined_bund) {
                   1543:            Link        const l = b->links[k];
                   1544: 
                   1545:            struct ng_ppp_link_stat     oldStats;
                   1546:        
                   1547:            /* Get updated link traffic statistics */
                   1548:            oldStats = l->bm.idleStats;
                   1549:            NgFuncGetStats(l->bund, l->bundleIndex, &l->bm.idleStats);
                   1550:            b->bm.traffic[0][0] += l->bm.idleStats.recvOctets - oldStats.recvOctets;
                   1551:            b->bm.traffic[1][0] += l->bm.idleStats.xmitOctets - oldStats.xmitOctets;
                   1552:        }
                   1553:     }
                   1554: 
                   1555:     /* Compute utilizations */
                   1556:     memset(&inUtil, 0, sizeof(inUtil));
                   1557:     memset(&outUtil, 0, sizeof(outUtil));
                   1558:     availTotal = inBitsTotal = outBitsTotal = 0;
                   1559:     for (j = 0; j < BUND_BM_N; j++) {
                   1560:        u_int   avail, inBits, outBits;
                   1561: 
                   1562:        avail = (b->bm.avail[j] * b->conf.bm_S) / BUND_BM_N;
                   1563:        inBits = b->bm.traffic[0][j] * 8;
                   1564:        outBits = b->bm.traffic[1][j] * 8;
                   1565: 
                   1566:        availTotal += avail;
                   1567:        inBitsTotal += inBits;
                   1568:        outBitsTotal += outBits;
                   1569: 
                   1570:        /* Compute bandwidth utilizations as percentages */
                   1571:        if (avail != 0) {
                   1572:            inUtil[j] = ((float) inBits / avail) * 100;
                   1573:            outUtil[j] = ((float) outBits / avail) * 100;
                   1574:        }
                   1575:     }
                   1576: 
                   1577:     /* Compute total averaged utilization */
                   1578:     if (availTotal != 0) {
                   1579:        inUtilTotal = ((float) inBitsTotal / availTotal) * 100;
                   1580:        outUtilTotal = ((float) outBitsTotal / availTotal) * 100;
                   1581:     }
                   1582: 
                   1583:   {
                   1584:     char       ins[100], outs[100];
                   1585: 
                   1586:     ins[0] = 0;
                   1587:     for (j = 0; j < BUND_BM_N; j++) {
                   1588:        snprintf(ins + strlen(ins), sizeof(ins) - strlen(ins),
                   1589:                " %3u ", b->bm.wasUp[BUND_BM_N - 1 - j]);
                   1590:     }
                   1591:     Log(LG_BUND2, ("[%s]                       %s", b->name, ins));
                   1592: 
                   1593:     snprintf(ins, sizeof(ins), " IN util: total %3u%%  ", inUtilTotal);
                   1594:     snprintf(outs, sizeof(outs), "OUT util: total %3u%%  ", outUtilTotal);
                   1595:     for (j = 0; j < BUND_BM_N; j++) {
                   1596:       snprintf(ins + strlen(ins), sizeof(ins) - strlen(ins),
                   1597:        " %3u%%", inUtil[BUND_BM_N - 1 - j]);
                   1598:       snprintf(outs + strlen(outs), sizeof(outs) - strlen(outs),
                   1599:        " %3u%%", outUtil[BUND_BM_N - 1 - j]);
                   1600:     }
                   1601:     Log(LG_BUND2, ("[%s] %s", b->name, ins));
                   1602:     Log(LG_BUND2, ("[%s] %s", b->name, outs));
                   1603:   }
                   1604: 
                   1605:   /* See if it's time to bring up another link */
                   1606:   if (now - b->bm.last_open >= b->conf.bm_Mc
                   1607:       && (inUtilTotal >= b->conf.bm_Hi || outUtilTotal >= b->conf.bm_Hi)) {
                   1608:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1609: cont:
                   1610:        if (!b->links[k] && b->conf.linkst[k][0])
                   1611:                break;
                   1612:     }
                   1613:     if (k < NG_PPP_MAX_LINKS) {
                   1614:        Log(LG_BUND, ("[%s] opening link \"%s\" due to increased demand",
                   1615:            b->name, b->conf.linkst[k]));
                   1616:        b->bm.last_open = now;
                   1617:        if (b->links[k]) {
                   1618:            RecordLinkUpDownReason(NULL, b->links[k], 1, STR_PORT_NEEDED, NULL);
                   1619:            BundOpenLink(b->links[k]);
                   1620:        } else {
                   1621:            if (BundCreateOpenLink(b, k)) {
                   1622:                if (k < NG_PPP_MAX_LINKS) {
                   1623:                    k++;
                   1624:                    goto cont;
                   1625:                }
                   1626:            } else
                   1627:                RecordLinkUpDownReason(NULL, b->links[k], 1, STR_PORT_NEEDED, NULL);
                   1628:        }
                   1629:     }
                   1630:   }
                   1631: 
                   1632:   /* See if it's time to bring down a link */
                   1633:   if (now - b->bm.last_close >= b->conf.bm_Md
                   1634:       && (inUtilTotal < b->conf.bm_Lo && outUtilTotal < b->conf.bm_Lo)
                   1635:       && b->n_links > 1) {
                   1636:     k = NG_PPP_MAX_LINKS - 1;
                   1637:     while (k >= 0 && (!b->links[k] || !OPEN_STATE(b->links[k]->lcp.fsm.state)))
                   1638:        k--;
                   1639:     assert(k >= 0);
                   1640:     Log(LG_BUND, ("[%s] Bundle: closing link %s due to reduced demand",
                   1641:       b->name, b->links[k]->name));
                   1642:     b->bm.last_close = now;
                   1643:     RecordLinkUpDownReason(NULL, b->links[k], 0, STR_PORT_UNNEEDED, NULL);
                   1644:     BundCloseLink(b->links[k]);
                   1645:   }
                   1646: 
                   1647:   /* Restart timer */
                   1648:   TimerStart(&b->bm.bmTimer);
                   1649: }
                   1650: 
                   1651: /*
                   1652:  * BundNgInit()
                   1653:  *
                   1654:  * Setup the initial PPP netgraph framework. Initializes these fields
                   1655:  * in the supplied bundle structure:
                   1656:  *
                   1657:  *     iface.ifname    - Interface name
                   1658:  *     csock           - Control socket for socket netgraph node
                   1659:  *     dsock           - Data socket for socket netgraph node
                   1660:  *
                   1661:  * Returns -1 if error.
                   1662:  */
                   1663: 
                   1664: static int
                   1665: BundNgInit(Bund b)
                   1666: {
                   1667:     struct ngm_mkpeer  mp;
                   1668:     struct ngm_name    nm;
                   1669:     int                        newIface = 0;
                   1670:     int                        newPpp = 0;
                   1671: 
                   1672:     /* Create new iface node */
                   1673:     if (NgFuncCreateIface(b,
                   1674:        b->iface.ifname, sizeof(b->iface.ifname)) < 0) {
                   1675:       Log(LG_ERR, ("[%s] can't create netgraph interface", b->name));
                   1676:       goto fail;
                   1677:     }
                   1678:     strlcpy(b->iface.ngname, b->iface.ifname, sizeof(b->iface.ngname));
                   1679:     newIface = 1;
                   1680:     b->iface.ifindex = if_nametoindex(b->iface.ifname);
                   1681:     Log(LG_BUND|LG_IFACE, ("[%s] Bundle: Interface %s created",
                   1682:        b->name, b->iface.ifname));
                   1683: 
                   1684:     /* Create new PPP node */
                   1685:     snprintf(b->hook, sizeof(b->hook), "b%d", b->id);
                   1686:     memset(&mp, 0, sizeof(mp));
                   1687:     strcpy(mp.type, NG_PPP_NODE_TYPE);
                   1688:     strcpy(mp.ourhook, b->hook);
                   1689:     strcpy(mp.peerhook, NG_PPP_HOOK_BYPASS);
                   1690:     if (NgSendMsg(gLinksCsock, ".:",
                   1691:            NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   1692:        Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
                   1693:            b->name, mp.type, ".:", mp.ourhook);
                   1694:        goto fail;
                   1695:     }
                   1696:     newPpp = 1;
                   1697: 
                   1698:     /* Get PPP node ID */
                   1699:     b->nodeID = NgGetNodeID(gLinksCsock, b->hook);
                   1700: 
                   1701:     /* Give it a name */
                   1702:     memset(&nm, 0, sizeof(nm));
                   1703:     snprintf(nm.name, sizeof(nm.name), "mpd%d-%s", gPid, b->name);
                   1704:     if (NgSendMsg(gLinksCsock, b->hook,
                   1705:            NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   1706:        Perror("[%s] can't name %s node \"%s\"",
                   1707:            b->name, NG_PPP_NODE_TYPE, b->hook);
                   1708:        goto fail;
                   1709:     }
                   1710: 
                   1711:     /* OK */
                   1712:     return(0);
                   1713: 
                   1714: fail:
                   1715:     BundNgShutdown(b, newIface, newPpp);
                   1716:     return(-1);
                   1717: }
                   1718: 
                   1719: /*
                   1720:  * NgFuncShutdown()
                   1721:  */
                   1722: 
                   1723: void
                   1724: BundNgShutdown(Bund b, int iface, int ppp)
                   1725: {
                   1726:     char       path[NG_PATHSIZ];
                   1727: 
                   1728:     if (iface) {
                   1729:        snprintf(path, sizeof(path), "%s:", b->iface.ngname);
                   1730:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   1731:     }
                   1732:     if (ppp) {
                   1733:        snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                   1734:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   1735:     }
                   1736:     b->hook[0] = 0;
                   1737: }
                   1738: 
                   1739: /*
                   1740:  * BundSetCommand()
                   1741:  */
                   1742: 
                   1743: static int
                   1744: BundSetCommand(Context ctx, int ac, char *av[], void *arg)
                   1745: {
                   1746:     Bund       b = ctx->bund;
                   1747:     int                i, val;
                   1748: 
                   1749:     if (ac == 0)
                   1750:        return(-1);
                   1751:     switch ((intptr_t)arg) {
                   1752:        case SET_PERIOD:
                   1753:            b->conf.bm_S = atoi(*av);
                   1754:            break;
                   1755:        case SET_LOW_WATER:
                   1756:            b->conf.bm_Lo = atoi(*av);
                   1757:            break;
                   1758:        case SET_HIGH_WATER:
                   1759:            b->conf.bm_Hi = atoi(*av);
                   1760:            break;
                   1761:        case SET_MIN_CONNECT:
                   1762:            b->conf.bm_Mc = atoi(*av);
                   1763:            break;
                   1764:        case SET_MIN_DISCONNECT:
                   1765:            b->conf.bm_Md = atoi(*av);
                   1766:            break;
                   1767:        case SET_LINKS:
                   1768:            if (ac > NG_PPP_MAX_LINKS)
                   1769:                return (-1);
                   1770:            for (i = 0; i < ac; i++)
                   1771:                strlcpy(b->conf.linkst[i], av[i], LINK_MAX_NAME);
                   1772:            for (; i < NG_PPP_MAX_LINKS; i++)
                   1773:                b->conf.linkst[i][0] = 0;
                   1774:            break;
                   1775: 
                   1776:        case SET_RETRY:
                   1777:            val = atoi(*av);
                   1778:            if (val < 1 || val > 10)
                   1779:                Error("[%s] incorrect fsm-timeout value %d", b->name, val);
                   1780:            else
                   1781:                b->conf.retry_timeout = val;
                   1782:            break;
                   1783: 
                   1784:        case SET_ACCEPT:
                   1785:            AcceptCommand(ac, av, &b->conf.options, gConfList);
                   1786:            break;
                   1787: 
                   1788:        case SET_DENY:
                   1789:            DenyCommand(ac, av, &b->conf.options, gConfList);
                   1790:            break;
                   1791: 
                   1792:        case SET_ENABLE:
                   1793:            EnableCommand(ac, av, &b->conf.options, gConfList);
                   1794:            break;
                   1795: 
                   1796:        case SET_DISABLE:
                   1797:            DisableCommand(ac, av, &b->conf.options, gConfList);
                   1798:            break;
                   1799: 
                   1800:        case SET_YES:
                   1801:            YesCommand(ac, av, &b->conf.options, gConfList);
                   1802:            break;
                   1803: 
                   1804:        case SET_NO:
                   1805:            NoCommand(ac, av, &b->conf.options, gConfList);
                   1806:            break;
                   1807: 
                   1808:        default:
                   1809:            assert(0);
                   1810:     }
                   1811:     return(0);
                   1812: }
                   1813: 

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