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

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,
1.1.1.3 ! misho     894:                  PhysGetMtu(b->links[the_link], 0));
1.1       misho     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;
1.1.1.2   misho    1138:                IfaceDestroy(b);
1.1       misho    1139:                Freee(b);
                   1140:                Error("Bundle netgraph initialization failed");
                   1141:            }
                   1142:        }
                   1143:     }
                   1144:   
                   1145:     RESETREF(ctx->bund, b);
                   1146:   
                   1147:     /* Done */
                   1148:     return(0);
                   1149: }
                   1150: 
                   1151: /*
                   1152:  * BundDestroy()
                   1153:  */
                   1154: 
                   1155: int
                   1156: BundDestroy(Context ctx, int ac, char *av[], void *arg)
                   1157: {
                   1158:     Bund       b;
                   1159: 
                   1160:     if (ac > 1)
                   1161:        return(-1);
                   1162: 
                   1163:     if (ac == 1) {
                   1164:        if ((b = BundFind(av[0])) == NULL)
                   1165:            Error("Bund \"%s\" not found", av[0]);
                   1166:     } else {
                   1167:        if (ctx->bund) {
                   1168:            b = ctx->bund;
                   1169:        } else
                   1170:            Error("No bundle selected to destroy");
                   1171:     }
                   1172:     
                   1173:     if (b->tmpl) {
                   1174:        b->tmpl = 0;
                   1175:        b->stay = 0;
                   1176:        BundShutdown(b);
                   1177:     } else {
                   1178:        b->stay = 0;
                   1179:        if (b->n_up) {
                   1180:            BundClose(b);
                   1181:        } else {
                   1182:            BundShutdown(b);
                   1183:        }
                   1184:     }
                   1185: 
                   1186:     return (0);
                   1187: }
                   1188: 
                   1189: /*
                   1190:  * BundInst()
                   1191:  */
                   1192: 
                   1193: Bund
                   1194: BundInst(Bund bt, char *name, int tmpl, int stay)
                   1195: {
                   1196:     Bund       b;
                   1197:     int        k;
                   1198: 
                   1199:     /* Create a new bundle structure */
                   1200:     b = Mdup(MB_BUND, bt, sizeof(*b));
                   1201:     b->tmpl = tmpl;
                   1202:     b->stay = stay;
                   1203:     b->refs = 0;
                   1204: 
                   1205:     /* Add bundle to the list of bundles and make it the current active bundle */
                   1206:     for (k = 0; k < gNumBundles && gBundles[k] != NULL; k++);
                   1207:     if (k == gNumBundles)                      /* add a new bundle pointer */
                   1208:        LengthenArray(&gBundles, sizeof(*gBundles), &gNumBundles, MB_BUND);
                   1209: 
                   1210:     b->id = k;
                   1211:     if (name)
                   1212:        strlcpy(b->name, name, sizeof(b->name));
                   1213:     else
                   1214:        snprintf(b->name, sizeof(b->name), "%s-%d", bt->name, k);
                   1215:     gBundles[k] = b;
                   1216:     REF(b);
                   1217: 
                   1218:     /* Inst iface and NCP's */
                   1219:     IfaceInst(b, bt);
                   1220:     IpcpInst(b, bt);
                   1221:     Ipv6cpInst(b, bt);
                   1222:     CcpInst(b, bt);
                   1223:     EcpInst(b, bt);
                   1224: 
                   1225:     if (!tmpl) {
                   1226:        /* Setup netgraph stuff */
                   1227:        if (BundNgInit(b) < 0) {
                   1228:            Log(LG_ERR, ("[%s] Bundle netgraph initialization failed", b->name));
                   1229:            gBundles[b->id] = NULL;
                   1230:            Freee(b);
                   1231:            return(0);
                   1232:        }
                   1233:     }
                   1234: 
                   1235:     return (b);
                   1236: }
                   1237: 
                   1238: /*
                   1239:  * BundShutdown()
                   1240:  *
                   1241:  * Shutdown the netgraph stuff associated with bundle
                   1242:  */
                   1243: 
                   1244: void
                   1245: BundShutdown(Bund b)
                   1246: {
                   1247:     Link       l;
                   1248:     int                k;
                   1249: 
                   1250:     Log(LG_BUND, ("[%s] Bundle: Shutdown", b->name));
                   1251:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1252:        if ((l = b->links[k]) != NULL) {
                   1253:            if (!l->stay)
                   1254:                LinkShutdown(l);
                   1255:            else {
                   1256:                l->bund = NULL;
                   1257:                b->links[k] = NULL;
                   1258:            }
                   1259:        }
                   1260:     }
                   1261: 
                   1262:     if (b->hook[0])
                   1263:        BundNgShutdown(b, 1, 1);
                   1264:     gBundles[b->id] = NULL;
                   1265:     MsgUnRegister(&b->msgs);
                   1266:     b->dead = 1;
                   1267:     IfaceDestroy(b);
                   1268:     UNREF(b);
                   1269: }
                   1270: 
                   1271: /*
                   1272:  * BundStat()
                   1273:  *
                   1274:  * Show state of a bundle
                   1275:  */
                   1276: 
                   1277: int
                   1278: BundStat(Context ctx, int ac, char *av[], void *arg)
                   1279: {
                   1280:   Bund sb;
                   1281:   int  k, bw, tbw, nup;
                   1282:   char buf[64];
                   1283: 
                   1284:   /* Find bundle they're talking about */
                   1285:   switch (ac) {
                   1286:     case 0:
                   1287:       sb = ctx->bund;
                   1288:       break;
                   1289:     case 1:
                   1290:       if ((sb = BundFind(av[0])) == NULL)
                   1291:        Error("Bundle \"%s\" not defined", av[0]);
                   1292:       break;
                   1293:     default:
                   1294:       return(-1);
                   1295:   }
                   1296: 
                   1297:   /* Show stuff about the bundle */
                   1298:   for (tbw = bw = nup = k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1299:     if (sb->links[k]) {
                   1300:        if (sb->links[k]->lcp.phase == PHASE_NETWORK) {
                   1301:            nup++;
                   1302:            bw += sb->links[k]->bandwidth;
                   1303:        }
                   1304:        tbw += sb->links[k]->bandwidth;
                   1305:     }
                   1306:   }
                   1307: 
                   1308:   Printf("Bundle '%s'%s:\r\n", sb->name, sb->tmpl?" (template)":(sb->stay?" (static)":""));
                   1309:   Printf("\tLinks          : ");
                   1310:   BundShowLinks(ctx, sb);
                   1311:   Printf("\tStatus         : %s\r\n", sb->open ? "OPEN" : "CLOSED");
                   1312:   if (sb->n_up)
                   1313:     Printf("\tSession time   : %ld seconds\r\n", (long int)(time(NULL) - sb->last_up));
                   1314:   Printf("\tMultiSession Id: %s\r\n", sb->msession_id);
                   1315:   Printf("\tTotal bandwidth: %u bits/sec\r\n", tbw);
                   1316:   Printf("\tAvail bandwidth: %u bits/sec\r\n", bw);
                   1317:   Printf("\tPeer authname  : \"%s\"\r\n", sb->params.authname);
                   1318: 
                   1319:   /* Show configuration */
                   1320:   Printf("Configuration:\r\n");
1.1.1.2   misho    1321: #ifdef SIOCSIFDESCR
                   1322:   Printf("\tDesc. template : %s\r\n",
                   1323:        sb->iface.conf.ifdescr ? sb->iface.conf.ifdescr : "<none>");
                   1324:   Printf("\tDescription    : %s\r\n",
                   1325:        sb->iface.ifdescr ? sb->iface.ifdescr : "<none>");
                   1326: #endif
1.1       misho    1327:   Printf("\tRetry timeout  : %d seconds\r\n", sb->conf.retry_timeout);
                   1328:   Printf("\tBW-manage:\r\n");
                   1329:   Printf("\t  Period       : %d seconds\r\n", sb->conf.bm_S);
                   1330:   Printf("\t  Low mark     : %d%%\r\n", sb->conf.bm_Lo);
                   1331:   Printf("\t  High mark    : %d%%\r\n", sb->conf.bm_Hi);
                   1332:   Printf("\t  Min conn     : %d seconds\r\n", sb->conf.bm_Mc);
                   1333:   Printf("\t  Min disc     : %d seconds\r\n", sb->conf.bm_Md);
                   1334:   Printf("\t  Links        : ");
                   1335:   for (k = 0; k < NG_PPP_MAX_LINKS; k++)
                   1336:     Printf("%s ", sb->conf.linkst[k]);
                   1337:   Printf("\r\n");
                   1338:   Printf("Bundle level options:\r\n");
                   1339:   OptStat(ctx, &sb->conf.options, gConfList);
                   1340: 
                   1341:     /* Show peer info */
                   1342:     Printf("Multilink PPP:\r\n");
                   1343:     Printf("\tStatus         : %s\r\n",
                   1344:        sb->peer_mrru ? "Active" : "Inactive");
                   1345:     if (sb->peer_mrru) {
                   1346:       Printf("\tPeer MRRU      : %d bytes\r\n", sb->peer_mrru);
                   1347:       Printf("\tPeer auth name : \"%s\"\r\n", sb->params.authname);
                   1348:       Printf("\tPeer discrimin.: %s\r\n", MpDiscrimText(&sb->peer_discrim, buf, sizeof(buf)));
                   1349:     }
                   1350: 
                   1351:     if (!sb->tmpl) {
                   1352:        /* Show stats */
                   1353:        BundUpdateStats(sb);
                   1354:        Printf("Traffic stats:\r\n");
                   1355: 
                   1356:        Printf("\tInput octets   : %llu\r\n", (unsigned long long)sb->stats.recvOctets);
                   1357:        Printf("\tInput frames   : %llu\r\n", (unsigned long long)sb->stats.recvFrames);
                   1358:        Printf("\tOutput octets  : %llu\r\n", (unsigned long long)sb->stats.xmitOctets);
                   1359:        Printf("\tOutput frames  : %llu\r\n", (unsigned long long)sb->stats.xmitFrames);
                   1360:        Printf("\tBad protocols  : %llu\r\n", (unsigned long long)sb->stats.badProtos);
                   1361:        Printf("\tRunts          : %llu\r\n", (unsigned long long)sb->stats.runts);
                   1362:        Printf("\tDup fragments  : %llu\r\n", (unsigned long long)sb->stats.dupFragments);
                   1363:        Printf("\tDrop fragments : %llu\r\n", (unsigned long long)sb->stats.dropFragments);
                   1364:     }
                   1365: 
                   1366:     return(0);
                   1367: }
                   1368: 
                   1369: /* 
                   1370:  * BundUpdateStats()
                   1371:  */
                   1372: 
                   1373: void
                   1374: BundUpdateStats(Bund b)
                   1375: {
                   1376: #ifndef NG_PPP_STATS64
                   1377:   struct ng_ppp_link_stat      stats;
                   1378: #endif
                   1379:   int  l = NG_PPP_BUNDLE_LINKNUM;
                   1380: 
                   1381: #if (__FreeBSD_version < 602104 || (__FreeBSD_version >= 700000 && __FreeBSD_version < 700029))
                   1382:   /* Workaround for broken ng_ppp bundle stats */
                   1383:   if (!b->peer_mrru)
                   1384:     l = 0;
                   1385: #endif
                   1386: 
                   1387: #ifndef NG_PPP_STATS64
                   1388:   if (NgFuncGetStats(b, l, &stats) != -1) {
                   1389:     b->stats.xmitFrames += abs(stats.xmitFrames - b->oldStats.xmitFrames);
                   1390:     b->stats.xmitOctets += abs(stats.xmitOctets - b->oldStats.xmitOctets);
                   1391:     b->stats.recvFrames += abs(stats.recvFrames - b->oldStats.recvFrames);
                   1392:     b->stats.recvOctets += abs(stats.recvOctets - b->oldStats.recvOctets);
                   1393:     b->stats.badProtos  += abs(stats.badProtos - b->oldStats.badProtos);
                   1394:     b->stats.runts       += abs(stats.runts - b->oldStats.runts);
                   1395:     b->stats.dupFragments += abs(stats.dupFragments - b->oldStats.dupFragments);
                   1396:     b->stats.dropFragments += abs(stats.dropFragments - b->oldStats.dropFragments);
                   1397:   }
                   1398: 
                   1399:   b->oldStats = stats;
                   1400: #else
                   1401:     NgFuncGetStats64(b, l, &b->stats);
                   1402: #endif
                   1403: }
                   1404: 
                   1405: /* 
                   1406:  * BundUpdateStatsTimer()
                   1407:  */
                   1408: 
                   1409: void
                   1410: BundUpdateStatsTimer(void *cookie)
                   1411: {
                   1412:     Bund       b = (Bund)cookie;
                   1413:     int                k;
                   1414:   
                   1415:     BundUpdateStats(b);
                   1416:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1417:        if (b->links[k] && b->links[k]->joined_bund)
                   1418:            LinkUpdateStats(b->links[k]);
                   1419:     }
                   1420: }
                   1421: 
                   1422: /*
                   1423:  * BundResetStats()
                   1424:  */
                   1425: 
                   1426: void
                   1427: BundResetStats(Bund b)
                   1428: {
                   1429:   NgFuncClrStats(b, NG_PPP_BUNDLE_LINKNUM);
                   1430:   memset(&b->stats, 0, sizeof(b->stats));
                   1431: #ifndef NG_PPP_STATS64
                   1432:   memset(&b->oldStats, 0, sizeof(b->oldStats));
                   1433: #endif
                   1434: }
                   1435: 
                   1436: /*
                   1437:  * BundShowLinks()
                   1438:  */
                   1439: 
                   1440: void
                   1441: BundShowLinks(Context ctx, Bund sb)
                   1442: {
                   1443:     int                j;
                   1444: 
                   1445:     for (j = 0; j < NG_PPP_MAX_LINKS; j++) {
                   1446:        if (sb->links[j]) {
                   1447:            Printf("%s[%s/%s] ", sb->links[j]->name,
                   1448:                FsmStateName(sb->links[j]->lcp.fsm.state),
                   1449:                gPhysStateNames[sb->links[j]->state]);
                   1450:        }
                   1451:     }
                   1452:     Printf("\r\n");
                   1453: }
                   1454: 
                   1455: /*
                   1456:  * BundFind()
                   1457:  *
                   1458:  * Find a bundle structure
                   1459:  */
                   1460: 
                   1461: Bund
                   1462: BundFind(const char *name)
                   1463: {
                   1464:   int  k;
                   1465: 
                   1466:   for (k = 0;
                   1467:     k < gNumBundles && (!gBundles[k] || strcmp(gBundles[k]->name, name));
                   1468:     k++);
                   1469:   return((k < gNumBundles) ? gBundles[k] : NULL);
                   1470: }
                   1471: 
                   1472: /*
                   1473:  * BundBmStart()
                   1474:  *
                   1475:  * Start bandwidth management timer
                   1476:  */
                   1477: 
                   1478: static void
                   1479: BundBmStart(Bund b)
                   1480: {
                   1481:     int        k;
                   1482: 
                   1483:     /* Reset bandwidth management stats */
                   1484:     memset(&b->bm.traffic, 0, sizeof(b->bm.traffic));
                   1485:     memset(&b->bm.avail, 0, sizeof(b->bm.avail));
                   1486:     memset(&b->bm.wasUp, 0, sizeof(b->bm.wasUp));
                   1487:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1488:        if (b->links[k]) {
                   1489:            memset(&b->links[k]->bm.idleStats,
                   1490:                0, sizeof(b->links[k]->bm.idleStats));
                   1491:        }
                   1492:     }
                   1493: 
                   1494:   /* Start bandwidth management timer */
                   1495:   TimerStop(&b->bm.bmTimer);
                   1496:   if (Enabled(&b->conf.options, BUND_CONF_BWMANAGE)) {
                   1497:     TimerInit(&b->bm.bmTimer, "BundBm",
                   1498:       (b->conf.bm_S * SECONDS) / BUND_BM_N,
                   1499:       BundBmTimeout, b);
                   1500:     TimerStart(&b->bm.bmTimer);
                   1501:   }
                   1502: }
                   1503: 
                   1504: /*
                   1505:  * BundBmStop()
                   1506:  */
                   1507: 
                   1508: static void
                   1509: BundBmStop(Bund b)
                   1510: {
                   1511:   TimerStop(&b->bm.bmTimer);
                   1512: }
                   1513: 
                   1514: /*
                   1515:  * BundBmTimeout()
                   1516:  *
                   1517:  * Do a bandwidth management update
                   1518:  */
                   1519: 
                   1520: static void
                   1521: BundBmTimeout(void *arg)
                   1522: {
                   1523:     Bund               b = (Bund)arg;
                   1524: 
                   1525:     const time_t       now = time(NULL);
                   1526:     u_int              availTotal;
                   1527:     u_int              inUtilTotal = 0, outUtilTotal = 0;
                   1528:     u_int              inBitsTotal, outBitsTotal;
                   1529:     u_int              inUtil[BUND_BM_N];      /* Incoming % utilization */
                   1530:     u_int              outUtil[BUND_BM_N];     /* Outgoing % utilization */
                   1531:     int                        j, k;
                   1532: 
                   1533:     /* Shift and update stats */
                   1534:     memmove(&b->bm.wasUp[1], &b->bm.wasUp[0],
                   1535:        (BUND_BM_N - 1) * sizeof(b->bm.wasUp[0]));
                   1536:     b->bm.wasUp[0] = b->n_up;
                   1537:     memmove(&b->bm.avail[1], &b->bm.avail[0],
                   1538:        (BUND_BM_N - 1) * sizeof(b->bm.avail[0]));
                   1539:     b->bm.avail[0] = b->bm.total_bw;
                   1540: 
                   1541:     /* Shift stats */
                   1542:     memmove(&b->bm.traffic[0][1], &b->bm.traffic[0][0],
                   1543:        (BUND_BM_N - 1) * sizeof(b->bm.traffic[0][0]));
                   1544:     memmove(&b->bm.traffic[1][1], &b->bm.traffic[1][0],
                   1545:        (BUND_BM_N - 1) * sizeof(b->bm.traffic[1][0]));
                   1546:     b->bm.traffic[0][0] = 0;
                   1547:     b->bm.traffic[1][0] = 0;
                   1548:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1549:        if (b->links[k] && b->links[k]->joined_bund) {
                   1550:            Link        const l = b->links[k];
                   1551: 
                   1552:            struct ng_ppp_link_stat     oldStats;
                   1553:        
                   1554:            /* Get updated link traffic statistics */
                   1555:            oldStats = l->bm.idleStats;
                   1556:            NgFuncGetStats(l->bund, l->bundleIndex, &l->bm.idleStats);
                   1557:            b->bm.traffic[0][0] += l->bm.idleStats.recvOctets - oldStats.recvOctets;
                   1558:            b->bm.traffic[1][0] += l->bm.idleStats.xmitOctets - oldStats.xmitOctets;
                   1559:        }
                   1560:     }
                   1561: 
                   1562:     /* Compute utilizations */
                   1563:     memset(&inUtil, 0, sizeof(inUtil));
                   1564:     memset(&outUtil, 0, sizeof(outUtil));
                   1565:     availTotal = inBitsTotal = outBitsTotal = 0;
                   1566:     for (j = 0; j < BUND_BM_N; j++) {
                   1567:        u_int   avail, inBits, outBits;
                   1568: 
                   1569:        avail = (b->bm.avail[j] * b->conf.bm_S) / BUND_BM_N;
                   1570:        inBits = b->bm.traffic[0][j] * 8;
                   1571:        outBits = b->bm.traffic[1][j] * 8;
                   1572: 
                   1573:        availTotal += avail;
                   1574:        inBitsTotal += inBits;
                   1575:        outBitsTotal += outBits;
                   1576: 
                   1577:        /* Compute bandwidth utilizations as percentages */
                   1578:        if (avail != 0) {
                   1579:            inUtil[j] = ((float) inBits / avail) * 100;
                   1580:            outUtil[j] = ((float) outBits / avail) * 100;
                   1581:        }
                   1582:     }
                   1583: 
                   1584:     /* Compute total averaged utilization */
                   1585:     if (availTotal != 0) {
                   1586:        inUtilTotal = ((float) inBitsTotal / availTotal) * 100;
                   1587:        outUtilTotal = ((float) outBitsTotal / availTotal) * 100;
                   1588:     }
                   1589: 
                   1590:   {
                   1591:     char       ins[100], outs[100];
                   1592: 
                   1593:     ins[0] = 0;
                   1594:     for (j = 0; j < BUND_BM_N; j++) {
                   1595:        snprintf(ins + strlen(ins), sizeof(ins) - strlen(ins),
                   1596:                " %3u ", b->bm.wasUp[BUND_BM_N - 1 - j]);
                   1597:     }
                   1598:     Log(LG_BUND2, ("[%s]                       %s", b->name, ins));
                   1599: 
                   1600:     snprintf(ins, sizeof(ins), " IN util: total %3u%%  ", inUtilTotal);
                   1601:     snprintf(outs, sizeof(outs), "OUT util: total %3u%%  ", outUtilTotal);
                   1602:     for (j = 0; j < BUND_BM_N; j++) {
                   1603:       snprintf(ins + strlen(ins), sizeof(ins) - strlen(ins),
                   1604:        " %3u%%", inUtil[BUND_BM_N - 1 - j]);
                   1605:       snprintf(outs + strlen(outs), sizeof(outs) - strlen(outs),
                   1606:        " %3u%%", outUtil[BUND_BM_N - 1 - j]);
                   1607:     }
                   1608:     Log(LG_BUND2, ("[%s] %s", b->name, ins));
                   1609:     Log(LG_BUND2, ("[%s] %s", b->name, outs));
                   1610:   }
                   1611: 
                   1612:   /* See if it's time to bring up another link */
                   1613:   if (now - b->bm.last_open >= b->conf.bm_Mc
                   1614:       && (inUtilTotal >= b->conf.bm_Hi || outUtilTotal >= b->conf.bm_Hi)) {
                   1615:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1616: cont:
                   1617:        if (!b->links[k] && b->conf.linkst[k][0])
                   1618:                break;
                   1619:     }
                   1620:     if (k < NG_PPP_MAX_LINKS) {
                   1621:        Log(LG_BUND, ("[%s] opening link \"%s\" due to increased demand",
                   1622:            b->name, b->conf.linkst[k]));
                   1623:        b->bm.last_open = now;
                   1624:        if (b->links[k]) {
                   1625:            RecordLinkUpDownReason(NULL, b->links[k], 1, STR_PORT_NEEDED, NULL);
                   1626:            BundOpenLink(b->links[k]);
                   1627:        } else {
                   1628:            if (BundCreateOpenLink(b, k)) {
                   1629:                if (k < NG_PPP_MAX_LINKS) {
                   1630:                    k++;
                   1631:                    goto cont;
                   1632:                }
                   1633:            } else
                   1634:                RecordLinkUpDownReason(NULL, b->links[k], 1, STR_PORT_NEEDED, NULL);
                   1635:        }
                   1636:     }
                   1637:   }
                   1638: 
                   1639:   /* See if it's time to bring down a link */
                   1640:   if (now - b->bm.last_close >= b->conf.bm_Md
                   1641:       && (inUtilTotal < b->conf.bm_Lo && outUtilTotal < b->conf.bm_Lo)
                   1642:       && b->n_links > 1) {
                   1643:     k = NG_PPP_MAX_LINKS - 1;
                   1644:     while (k >= 0 && (!b->links[k] || !OPEN_STATE(b->links[k]->lcp.fsm.state)))
                   1645:        k--;
                   1646:     assert(k >= 0);
                   1647:     Log(LG_BUND, ("[%s] Bundle: closing link %s due to reduced demand",
                   1648:       b->name, b->links[k]->name));
                   1649:     b->bm.last_close = now;
                   1650:     RecordLinkUpDownReason(NULL, b->links[k], 0, STR_PORT_UNNEEDED, NULL);
                   1651:     BundCloseLink(b->links[k]);
                   1652:   }
                   1653: 
                   1654:   /* Restart timer */
                   1655:   TimerStart(&b->bm.bmTimer);
                   1656: }
                   1657: 
                   1658: /*
                   1659:  * BundNgInit()
                   1660:  *
                   1661:  * Setup the initial PPP netgraph framework. Initializes these fields
                   1662:  * in the supplied bundle structure:
                   1663:  *
                   1664:  *     iface.ifname    - Interface name
                   1665:  *     csock           - Control socket for socket netgraph node
                   1666:  *     dsock           - Data socket for socket netgraph node
                   1667:  *
                   1668:  * Returns -1 if error.
                   1669:  */
                   1670: 
                   1671: static int
                   1672: BundNgInit(Bund b)
                   1673: {
                   1674:     struct ngm_mkpeer  mp;
                   1675:     struct ngm_name    nm;
                   1676:     int                        newIface = 0;
                   1677:     int                        newPpp = 0;
                   1678: 
                   1679:     /* Create new iface node */
                   1680:     if (NgFuncCreateIface(b,
                   1681:        b->iface.ifname, sizeof(b->iface.ifname)) < 0) {
                   1682:       Log(LG_ERR, ("[%s] can't create netgraph interface", b->name));
                   1683:       goto fail;
                   1684:     }
                   1685:     strlcpy(b->iface.ngname, b->iface.ifname, sizeof(b->iface.ngname));
                   1686:     newIface = 1;
                   1687:     b->iface.ifindex = if_nametoindex(b->iface.ifname);
                   1688:     Log(LG_BUND|LG_IFACE, ("[%s] Bundle: Interface %s created",
                   1689:        b->name, b->iface.ifname));
                   1690: 
                   1691:     /* Create new PPP node */
                   1692:     snprintf(b->hook, sizeof(b->hook), "b%d", b->id);
                   1693:     memset(&mp, 0, sizeof(mp));
                   1694:     strcpy(mp.type, NG_PPP_NODE_TYPE);
                   1695:     strcpy(mp.ourhook, b->hook);
                   1696:     strcpy(mp.peerhook, NG_PPP_HOOK_BYPASS);
                   1697:     if (NgSendMsg(gLinksCsock, ".:",
                   1698:            NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   1699:        Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
                   1700:            b->name, mp.type, ".:", mp.ourhook);
                   1701:        goto fail;
                   1702:     }
                   1703:     newPpp = 1;
                   1704: 
                   1705:     /* Get PPP node ID */
                   1706:     b->nodeID = NgGetNodeID(gLinksCsock, b->hook);
                   1707: 
                   1708:     /* Give it a name */
                   1709:     memset(&nm, 0, sizeof(nm));
                   1710:     snprintf(nm.name, sizeof(nm.name), "mpd%d-%s", gPid, b->name);
                   1711:     if (NgSendMsg(gLinksCsock, b->hook,
                   1712:            NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   1713:        Perror("[%s] can't name %s node \"%s\"",
                   1714:            b->name, NG_PPP_NODE_TYPE, b->hook);
                   1715:        goto fail;
                   1716:     }
                   1717: 
                   1718:     /* OK */
                   1719:     return(0);
                   1720: 
                   1721: fail:
                   1722:     BundNgShutdown(b, newIface, newPpp);
                   1723:     return(-1);
                   1724: }
                   1725: 
                   1726: /*
                   1727:  * NgFuncShutdown()
                   1728:  */
                   1729: 
                   1730: void
                   1731: BundNgShutdown(Bund b, int iface, int ppp)
                   1732: {
                   1733:     char       path[NG_PATHSIZ];
                   1734: 
                   1735:     if (iface) {
                   1736:        snprintf(path, sizeof(path), "%s:", b->iface.ngname);
                   1737:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   1738:     }
                   1739:     if (ppp) {
                   1740:        snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                   1741:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   1742:     }
                   1743:     b->hook[0] = 0;
                   1744: }
                   1745: 
                   1746: /*
                   1747:  * BundSetCommand()
                   1748:  */
                   1749: 
                   1750: static int
                   1751: BundSetCommand(Context ctx, int ac, char *av[], void *arg)
                   1752: {
                   1753:     Bund       b = ctx->bund;
                   1754:     int                i, val;
                   1755: 
                   1756:     if (ac == 0)
                   1757:        return(-1);
                   1758:     switch ((intptr_t)arg) {
                   1759:        case SET_PERIOD:
                   1760:            b->conf.bm_S = atoi(*av);
                   1761:            break;
                   1762:        case SET_LOW_WATER:
                   1763:            b->conf.bm_Lo = atoi(*av);
                   1764:            break;
                   1765:        case SET_HIGH_WATER:
                   1766:            b->conf.bm_Hi = atoi(*av);
                   1767:            break;
                   1768:        case SET_MIN_CONNECT:
                   1769:            b->conf.bm_Mc = atoi(*av);
                   1770:            break;
                   1771:        case SET_MIN_DISCONNECT:
                   1772:            b->conf.bm_Md = atoi(*av);
                   1773:            break;
                   1774:        case SET_LINKS:
                   1775:            if (ac > NG_PPP_MAX_LINKS)
                   1776:                return (-1);
                   1777:            for (i = 0; i < ac; i++)
                   1778:                strlcpy(b->conf.linkst[i], av[i], LINK_MAX_NAME);
                   1779:            for (; i < NG_PPP_MAX_LINKS; i++)
                   1780:                b->conf.linkst[i][0] = 0;
                   1781:            break;
                   1782: 
                   1783:        case SET_RETRY:
                   1784:            val = atoi(*av);
                   1785:            if (val < 1 || val > 10)
                   1786:                Error("[%s] incorrect fsm-timeout value %d", b->name, val);
                   1787:            else
                   1788:                b->conf.retry_timeout = val;
                   1789:            break;
                   1790: 
                   1791:        case SET_ACCEPT:
                   1792:            AcceptCommand(ac, av, &b->conf.options, gConfList);
                   1793:            break;
                   1794: 
                   1795:        case SET_DENY:
                   1796:            DenyCommand(ac, av, &b->conf.options, gConfList);
                   1797:            break;
                   1798: 
                   1799:        case SET_ENABLE:
                   1800:            EnableCommand(ac, av, &b->conf.options, gConfList);
                   1801:            break;
                   1802: 
                   1803:        case SET_DISABLE:
                   1804:            DisableCommand(ac, av, &b->conf.options, gConfList);
                   1805:            break;
                   1806: 
                   1807:        case SET_YES:
                   1808:            YesCommand(ac, av, &b->conf.options, gConfList);
                   1809:            break;
                   1810: 
                   1811:        case SET_NO:
                   1812:            NoCommand(ac, av, &b->conf.options, gConfList);
                   1813:            break;
                   1814: 
                   1815:        default:
                   1816:            assert(0);
                   1817:     }
                   1818:     return(0);
                   1819: }
                   1820: 

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