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

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

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