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

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);
1.1.1.5 ! misho      75:   static int   BundSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1       misho      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 },
1.1.1.5 ! misho     118:     { NULL, NULL, NULL, NULL, 0, NULL },
1.1       misho     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
1.1.1.5 ! misho     921: BundCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     922: {
                    923:     Bund       sb;
                    924:     int                j, k;
                    925: 
1.1.1.5 ! misho     926:     (void)arg;
        !           927: 
1.1       misho     928:     if (ac > 1)
                    929:        return (-1);
                    930: 
                    931:     if (ac == 0) {
                    932:        Printf("Defined bundles:\r\n");
                    933:        for (k = 0; k < gNumBundles; k++) {
                    934:            if ((sb = gBundles[k]) != NULL) {
                    935:                Printf("\t%-15s", sb->name);
                    936:                for (j = 0; j < NG_PPP_MAX_LINKS; j++) {
                    937:                    if (sb->links[j])
                    938:                        Printf("%s ", sb->links[j]->name);
                    939:                }
                    940:                Printf("\r\n");
                    941:            }
                    942:        }
                    943:        return (0);
                    944:     }
                    945: 
                    946:     if ((sb = BundFind(av[0])) == NULL) {
                    947:         RESETREF(ctx->lnk, NULL);
                    948:        RESETREF(ctx->bund, NULL);
                    949:        RESETREF(ctx->rep, NULL);
                    950:         Error("Bundle \"%s\" not defined.", av[0]);
                    951:     }
                    952: 
                    953:     /* Change bundle, and link also if needed */
                    954:     RESETREF(ctx->bund, sb);
                    955:     if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
                    956:         RESETREF(ctx->lnk, ctx->bund->links[0]);
                    957:     }
                    958:     RESETREF(ctx->rep, NULL);
                    959:     return(0);
                    960: }
                    961: 
                    962: /*
                    963:  * MSessionCommand()
                    964:  */
                    965: 
                    966: int
1.1.1.5 ! misho     967: MSessionCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     968: {
                    969:     int                k;
                    970: 
1.1.1.5 ! misho     971:     (void)arg;
        !           972: 
1.1       misho     973:     if (ac > 1)
                    974:        return (-1);
                    975: 
                    976:     if (ac == 0) {
                    977:        Printf("Present msessions:\r\n");
                    978:        for (k = 0; k < gNumBundles; k++) {
                    979:            if (gBundles[k] && gBundles[k]->msession_id[0])
                    980:                Printf("\t%s\r\n", gBundles[k]->msession_id);
                    981:        }
                    982:        return (0);
                    983:     }
                    984: 
                    985:     /* Find bundle */
                    986:     for (k = 0;
                    987:        k < gNumBundles && (gBundles[k] == NULL || 
                    988:            strcmp(gBundles[k]->msession_id, av[0]));
                    989:        k++);
                    990:     if (k == gNumBundles) {
                    991:        /* Change default link and bundle */
                    992:        RESETREF(ctx->lnk, NULL);
                    993:        RESETREF(ctx->bund, NULL);
                    994:        RESETREF(ctx->rep, NULL);
                    995:        Error("msession \"%s\" is not found", av[0]);
                    996:     }
                    997: 
                    998:     /* Change default link and bundle */
                    999:     RESETREF(ctx->bund, gBundles[k]);
                   1000:     if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
                   1001:         RESETREF(ctx->lnk, ctx->bund->links[0]);
                   1002:     }
                   1003:     RESETREF(ctx->rep, NULL);
                   1004: 
                   1005:     return(0);
                   1006: }
                   1007: 
                   1008: /*
                   1009:  * IfaceCommand()
                   1010:  */
                   1011: 
                   1012: int
1.1.1.5 ! misho    1013: IfaceCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1014: {
                   1015:     int                k;
                   1016: 
1.1.1.5 ! misho    1017:     (void)arg;
        !          1018: 
1.1       misho    1019:     if (ac > 1)
                   1020:        return (-1);
                   1021: 
                   1022:     if (ac == 0) {
                   1023:        Printf("Present ifaces:\r\n");
                   1024:        for (k = 0; k < gNumBundles; k++) {
                   1025:            if (gBundles[k] && gBundles[k]->iface.ifname[0])
                   1026:                Printf("\t%s\t%s\r\n", gBundles[k]->iface.ifname, gBundles[k]->name);
                   1027:        }
                   1028:        return (0);
                   1029:     }
                   1030: 
                   1031:     /* Find bundle */
                   1032:     for (k = 0;
                   1033:        k < gNumBundles && (gBundles[k] == NULL || 
                   1034:            strcmp(gBundles[k]->iface.ifname, av[0]));
                   1035:        k++);
                   1036:     if (k == gNumBundles) {
                   1037:        /* Change default link and bundle */
                   1038:        RESETREF(ctx->lnk, NULL);
                   1039:        RESETREF(ctx->bund, NULL);
                   1040:        RESETREF(ctx->rep, NULL);
                   1041:        Error("iface \"%s\" is not found", av[0]);
                   1042:     }
                   1043: 
                   1044:     /* Change default link and bundle */
                   1045:     RESETREF(ctx->bund, gBundles[k]);
                   1046:     if (ctx->lnk == NULL || ctx->lnk->bund != ctx->bund) {
                   1047:         RESETREF(ctx->lnk, ctx->bund->links[0]);
                   1048:     }
                   1049:     RESETREF(ctx->rep, NULL);
                   1050: 
                   1051:     return(0);
                   1052: }
                   1053: 
                   1054: /*
                   1055:  * BundCreate()
                   1056:  */
                   1057: 
                   1058: int
1.1.1.5 ! misho    1059: BundCreate(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1060: {
                   1061:     Bund       b, bt = NULL;
                   1062:     u_char     tmpl = 0;
                   1063:     u_char     stay = 0;
                   1064:     int        k;
                   1065: 
1.1.1.5 ! misho    1066:     (void)arg;
        !          1067: 
1.1       misho    1068:     RESETREF(ctx->lnk, NULL);
                   1069:     RESETREF(ctx->bund, NULL);
                   1070:     RESETREF(ctx->rep, NULL);
                   1071: 
                   1072:     if (ac < 1)
                   1073:        return(-1);
                   1074: 
                   1075:     if (strcmp(av[0], "template") == 0) {
                   1076:        tmpl = 1;
                   1077:        stay = 1;
                   1078:     } else if (strcmp(av[0], "static") == 0)
                   1079:        stay = 1;
                   1080: 
                   1081:     if (ac - stay < 1 || ac - stay > 2)
                   1082:        return(-1);
                   1083: 
                   1084:     if (strlen(av[0 + stay]) >= (LINK_MAX_NAME - tmpl * (IFNUMLEN + 1)))
                   1085:        Error("Bundle name \"%s\" is too long", av[0 + stay]);
                   1086: 
                   1087:     /* See if bundle name already taken */
                   1088:     if ((b = BundFind(av[0 + stay])) != NULL)
                   1089:        Error("Bundle \"%s\" already exists", av[0 + stay]);
                   1090: 
                   1091:     if (ac - stay == 2) {
                   1092:        /* See if template name specified */
                   1093:        if ((bt = BundFind(av[1 + stay])) == NULL)
                   1094:            Error("Bundle template \"%s\" not found", av[1 + stay]);
                   1095:        if (!bt->tmpl)
                   1096:            Error("Bundle \"%s\" is not a template", av[1 + stay]);
                   1097:     }
                   1098: 
                   1099:     if (bt) {
                   1100:        b = BundInst(bt, av[0 + stay], tmpl, stay);
                   1101:     } else {
                   1102:        /* Create a new bundle structure */
                   1103:        b = Malloc(MB_BUND, sizeof(*b));
                   1104:        strlcpy(b->name, av[0 + stay], sizeof(b->name));
                   1105:        b->tmpl = tmpl;
                   1106:        b->stay = stay;
                   1107: 
                   1108:        /* Add bundle to the list of bundles and make it the current active bundle */
                   1109:        for (k = 0; k < gNumBundles && gBundles[k] != NULL; k++);
                   1110:        if (k == gNumBundles)                   /* add a new bundle pointer */
                   1111:            LengthenArray(&gBundles, sizeof(*gBundles), &gNumBundles, MB_BUND);
                   1112: 
                   1113:        b->id = k;
                   1114:        gBundles[k] = b;
                   1115:        REF(b);
                   1116: 
                   1117:        /* Get message channel */
                   1118:        MsgRegister(&b->msgs, BundMsg);
                   1119: 
                   1120:        /* Initialize bundle configuration */
                   1121:        b->conf.retry_timeout = BUND_DEFAULT_RETRY;
                   1122:        b->conf.bm_S = BUND_BM_DFL_S;
                   1123:        b->conf.bm_Hi = BUND_BM_DFL_Hi;
                   1124:        b->conf.bm_Lo = BUND_BM_DFL_Lo;
                   1125:        b->conf.bm_Mc = BUND_BM_DFL_Mc;
                   1126:        b->conf.bm_Md = BUND_BM_DFL_Md;
                   1127: 
                   1128:        Enable(&b->conf.options, BUND_CONF_IPCP);
                   1129:        Disable(&b->conf.options, BUND_CONF_IPV6CP);
                   1130: 
                   1131:        Disable(&b->conf.options, BUND_CONF_BWMANAGE);
                   1132:        Disable(&b->conf.options, BUND_CONF_COMPRESSION);
                   1133:        Disable(&b->conf.options, BUND_CONF_ENCRYPTION);
                   1134:         Disable(&b->conf.options, BUND_CONF_CRYPT_REQD);
                   1135:   
                   1136:         /* Init iface and NCP's */
                   1137:        IfaceInit(b);
                   1138:         IpcpInit(b);
                   1139:         Ipv6cpInit(b);
                   1140:         CcpInit(b);
                   1141:         EcpInit(b);
                   1142: 
                   1143:        if (!tmpl) {
                   1144:            /* Setup netgraph stuff */
                   1145:            if (BundNgInit(b) < 0) {
                   1146:                gBundles[b->id] = NULL;
1.1.1.2   misho    1147:                IfaceDestroy(b);
1.1       misho    1148:                Freee(b);
                   1149:                Error("Bundle netgraph initialization failed");
                   1150:            }
                   1151:        }
                   1152:     }
                   1153:   
                   1154:     RESETREF(ctx->bund, b);
                   1155:   
                   1156:     /* Done */
                   1157:     return(0);
                   1158: }
                   1159: 
                   1160: /*
                   1161:  * BundDestroy()
                   1162:  */
                   1163: 
                   1164: int
1.1.1.5 ! misho    1165: BundDestroy(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1166: {
                   1167:     Bund       b;
                   1168: 
1.1.1.5 ! misho    1169:     (void)arg;
        !          1170: 
1.1       misho    1171:     if (ac > 1)
                   1172:        return(-1);
                   1173: 
                   1174:     if (ac == 1) {
                   1175:        if ((b = BundFind(av[0])) == NULL)
                   1176:            Error("Bund \"%s\" not found", av[0]);
                   1177:     } else {
                   1178:        if (ctx->bund) {
                   1179:            b = ctx->bund;
                   1180:        } else
                   1181:            Error("No bundle selected to destroy");
                   1182:     }
                   1183:     
                   1184:     if (b->tmpl) {
                   1185:        b->tmpl = 0;
                   1186:        b->stay = 0;
                   1187:        BundShutdown(b);
                   1188:     } else {
                   1189:        b->stay = 0;
                   1190:        if (b->n_up) {
                   1191:            BundClose(b);
                   1192:        } else {
                   1193:            BundShutdown(b);
                   1194:        }
                   1195:     }
                   1196: 
                   1197:     return (0);
                   1198: }
                   1199: 
                   1200: /*
                   1201:  * BundInst()
                   1202:  */
                   1203: 
                   1204: Bund
1.1.1.5 ! misho    1205: BundInst(Bund bt, const char *name, int tmpl, int stay)
1.1       misho    1206: {
                   1207:     Bund       b;
                   1208:     int        k;
                   1209: 
                   1210:     /* Create a new bundle structure */
                   1211:     b = Mdup(MB_BUND, bt, sizeof(*b));
                   1212:     b->tmpl = tmpl;
                   1213:     b->stay = stay;
                   1214:     b->refs = 0;
                   1215: 
                   1216:     /* Add bundle to the list of bundles and make it the current active bundle */
                   1217:     for (k = 0; k < gNumBundles && gBundles[k] != NULL; k++);
                   1218:     if (k == gNumBundles)                      /* add a new bundle pointer */
                   1219:        LengthenArray(&gBundles, sizeof(*gBundles), &gNumBundles, MB_BUND);
                   1220: 
                   1221:     b->id = k;
                   1222:     if (name)
                   1223:        strlcpy(b->name, name, sizeof(b->name));
                   1224:     else
                   1225:        snprintf(b->name, sizeof(b->name), "%s-%d", bt->name, k);
                   1226:     gBundles[k] = b;
                   1227:     REF(b);
                   1228: 
                   1229:     /* Inst iface and NCP's */
                   1230:     IfaceInst(b, bt);
                   1231:     IpcpInst(b, bt);
                   1232:     Ipv6cpInst(b, bt);
                   1233:     CcpInst(b, bt);
                   1234:     EcpInst(b, bt);
                   1235: 
                   1236:     if (!tmpl) {
                   1237:        /* Setup netgraph stuff */
                   1238:        if (BundNgInit(b) < 0) {
                   1239:            Log(LG_ERR, ("[%s] Bundle netgraph initialization failed", b->name));
                   1240:            gBundles[b->id] = NULL;
                   1241:            Freee(b);
                   1242:            return(0);
                   1243:        }
                   1244:     }
                   1245: 
                   1246:     return (b);
                   1247: }
                   1248: 
                   1249: /*
                   1250:  * BundShutdown()
                   1251:  *
                   1252:  * Shutdown the netgraph stuff associated with bundle
                   1253:  */
                   1254: 
                   1255: void
                   1256: BundShutdown(Bund b)
                   1257: {
                   1258:     Link       l;
                   1259:     int                k;
                   1260: 
                   1261:     Log(LG_BUND, ("[%s] Bundle: Shutdown", b->name));
                   1262:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1263:        if ((l = b->links[k]) != NULL) {
                   1264:            if (!l->stay)
                   1265:                LinkShutdown(l);
                   1266:            else {
                   1267:                l->bund = NULL;
                   1268:                b->links[k] = NULL;
                   1269:            }
                   1270:        }
                   1271:     }
                   1272: 
                   1273:     if (b->hook[0])
                   1274:        BundNgShutdown(b, 1, 1);
                   1275:     gBundles[b->id] = NULL;
                   1276:     MsgUnRegister(&b->msgs);
                   1277:     b->dead = 1;
                   1278:     IfaceDestroy(b);
                   1279:     UNREF(b);
                   1280: }
                   1281: 
                   1282: /*
                   1283:  * BundStat()
                   1284:  *
                   1285:  * Show state of a bundle
                   1286:  */
                   1287: 
                   1288: int
1.1.1.5 ! misho    1289: BundStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1290: {
                   1291:   Bund sb;
                   1292:   int  k, bw, tbw, nup;
                   1293:   char buf[64];
                   1294: 
1.1.1.5 ! misho    1295:   (void)arg;
        !          1296: 
1.1       misho    1297:   /* Find bundle they're talking about */
                   1298:   switch (ac) {
                   1299:     case 0:
                   1300:       sb = ctx->bund;
                   1301:       break;
                   1302:     case 1:
                   1303:       if ((sb = BundFind(av[0])) == NULL)
                   1304:        Error("Bundle \"%s\" not defined", av[0]);
                   1305:       break;
                   1306:     default:
                   1307:       return(-1);
                   1308:   }
                   1309: 
                   1310:   /* Show stuff about the bundle */
                   1311:   for (tbw = bw = nup = k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1312:     if (sb->links[k]) {
                   1313:        if (sb->links[k]->lcp.phase == PHASE_NETWORK) {
                   1314:            nup++;
                   1315:            bw += sb->links[k]->bandwidth;
                   1316:        }
                   1317:        tbw += sb->links[k]->bandwidth;
                   1318:     }
                   1319:   }
                   1320: 
                   1321:   Printf("Bundle '%s'%s:\r\n", sb->name, sb->tmpl?" (template)":(sb->stay?" (static)":""));
                   1322:   Printf("\tLinks          : ");
                   1323:   BundShowLinks(ctx, sb);
                   1324:   Printf("\tStatus         : %s\r\n", sb->open ? "OPEN" : "CLOSED");
                   1325:   if (sb->n_up)
                   1326:     Printf("\tSession time   : %ld seconds\r\n", (long int)(time(NULL) - sb->last_up));
                   1327:   Printf("\tMultiSession Id: %s\r\n", sb->msession_id);
                   1328:   Printf("\tTotal bandwidth: %u bits/sec\r\n", tbw);
                   1329:   Printf("\tAvail bandwidth: %u bits/sec\r\n", bw);
                   1330:   Printf("\tPeer authname  : \"%s\"\r\n", sb->params.authname);
                   1331: 
                   1332:   /* Show configuration */
                   1333:   Printf("Configuration:\r\n");
1.1.1.2   misho    1334: #ifdef SIOCSIFDESCR
                   1335:   Printf("\tDesc. template : %s\r\n",
                   1336:        sb->iface.conf.ifdescr ? sb->iface.conf.ifdescr : "<none>");
                   1337:   Printf("\tDescription    : %s\r\n",
                   1338:        sb->iface.ifdescr ? sb->iface.ifdescr : "<none>");
                   1339: #endif
1.1       misho    1340:   Printf("\tRetry timeout  : %d seconds\r\n", sb->conf.retry_timeout);
                   1341:   Printf("\tBW-manage:\r\n");
                   1342:   Printf("\t  Period       : %d seconds\r\n", sb->conf.bm_S);
                   1343:   Printf("\t  Low mark     : %d%%\r\n", sb->conf.bm_Lo);
                   1344:   Printf("\t  High mark    : %d%%\r\n", sb->conf.bm_Hi);
                   1345:   Printf("\t  Min conn     : %d seconds\r\n", sb->conf.bm_Mc);
                   1346:   Printf("\t  Min disc     : %d seconds\r\n", sb->conf.bm_Md);
                   1347:   Printf("\t  Links        : ");
                   1348:   for (k = 0; k < NG_PPP_MAX_LINKS; k++)
                   1349:     Printf("%s ", sb->conf.linkst[k]);
                   1350:   Printf("\r\n");
                   1351:   Printf("Bundle level options:\r\n");
                   1352:   OptStat(ctx, &sb->conf.options, gConfList);
                   1353: 
                   1354:     /* Show peer info */
                   1355:     Printf("Multilink PPP:\r\n");
                   1356:     Printf("\tStatus         : %s\r\n",
                   1357:        sb->peer_mrru ? "Active" : "Inactive");
                   1358:     if (sb->peer_mrru) {
                   1359:       Printf("\tPeer MRRU      : %d bytes\r\n", sb->peer_mrru);
                   1360:       Printf("\tPeer auth name : \"%s\"\r\n", sb->params.authname);
                   1361:       Printf("\tPeer discrimin.: %s\r\n", MpDiscrimText(&sb->peer_discrim, buf, sizeof(buf)));
                   1362:     }
                   1363: 
                   1364:     if (!sb->tmpl) {
                   1365:        /* Show stats */
                   1366:        BundUpdateStats(sb);
                   1367:        Printf("Traffic stats:\r\n");
                   1368: 
                   1369:        Printf("\tInput octets   : %llu\r\n", (unsigned long long)sb->stats.recvOctets);
                   1370:        Printf("\tInput frames   : %llu\r\n", (unsigned long long)sb->stats.recvFrames);
                   1371:        Printf("\tOutput octets  : %llu\r\n", (unsigned long long)sb->stats.xmitOctets);
                   1372:        Printf("\tOutput frames  : %llu\r\n", (unsigned long long)sb->stats.xmitFrames);
                   1373:        Printf("\tBad protocols  : %llu\r\n", (unsigned long long)sb->stats.badProtos);
                   1374:        Printf("\tRunts          : %llu\r\n", (unsigned long long)sb->stats.runts);
                   1375:        Printf("\tDup fragments  : %llu\r\n", (unsigned long long)sb->stats.dupFragments);
                   1376:        Printf("\tDrop fragments : %llu\r\n", (unsigned long long)sb->stats.dropFragments);
                   1377:     }
                   1378: 
                   1379:     return(0);
                   1380: }
                   1381: 
                   1382: /* 
                   1383:  * BundUpdateStats()
                   1384:  */
                   1385: 
                   1386: void
                   1387: BundUpdateStats(Bund b)
                   1388: {
                   1389: #ifndef NG_PPP_STATS64
                   1390:   struct ng_ppp_link_stat      stats;
                   1391: #endif
                   1392:   int  l = NG_PPP_BUNDLE_LINKNUM;
                   1393: 
                   1394: #if (__FreeBSD_version < 602104 || (__FreeBSD_version >= 700000 && __FreeBSD_version < 700029))
                   1395:   /* Workaround for broken ng_ppp bundle stats */
                   1396:   if (!b->peer_mrru)
                   1397:     l = 0;
                   1398: #endif
                   1399: 
                   1400: #ifndef NG_PPP_STATS64
                   1401:   if (NgFuncGetStats(b, l, &stats) != -1) {
                   1402:     b->stats.xmitFrames += abs(stats.xmitFrames - b->oldStats.xmitFrames);
                   1403:     b->stats.xmitOctets += abs(stats.xmitOctets - b->oldStats.xmitOctets);
                   1404:     b->stats.recvFrames += abs(stats.recvFrames - b->oldStats.recvFrames);
                   1405:     b->stats.recvOctets += abs(stats.recvOctets - b->oldStats.recvOctets);
                   1406:     b->stats.badProtos  += abs(stats.badProtos - b->oldStats.badProtos);
                   1407:     b->stats.runts       += abs(stats.runts - b->oldStats.runts);
                   1408:     b->stats.dupFragments += abs(stats.dupFragments - b->oldStats.dupFragments);
                   1409:     b->stats.dropFragments += abs(stats.dropFragments - b->oldStats.dropFragments);
1.1.1.4   misho    1410:     b->oldStats = stats;
1.1       misho    1411:   }
                   1412: 
                   1413: #else
                   1414:     NgFuncGetStats64(b, l, &b->stats);
                   1415: #endif
                   1416: }
                   1417: 
                   1418: /* 
                   1419:  * BundUpdateStatsTimer()
                   1420:  */
                   1421: 
                   1422: void
                   1423: BundUpdateStatsTimer(void *cookie)
                   1424: {
                   1425:     Bund       b = (Bund)cookie;
                   1426:     int                k;
                   1427:   
                   1428:     BundUpdateStats(b);
                   1429:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1430:        if (b->links[k] && b->links[k]->joined_bund)
                   1431:            LinkUpdateStats(b->links[k]);
                   1432:     }
                   1433: }
                   1434: 
                   1435: /*
                   1436:  * BundResetStats()
                   1437:  */
                   1438: 
                   1439: void
                   1440: BundResetStats(Bund b)
                   1441: {
                   1442:   NgFuncClrStats(b, NG_PPP_BUNDLE_LINKNUM);
                   1443:   memset(&b->stats, 0, sizeof(b->stats));
                   1444: #ifndef NG_PPP_STATS64
                   1445:   memset(&b->oldStats, 0, sizeof(b->oldStats));
                   1446: #endif
                   1447: }
                   1448: 
                   1449: /*
                   1450:  * BundShowLinks()
                   1451:  */
                   1452: 
                   1453: void
                   1454: BundShowLinks(Context ctx, Bund sb)
                   1455: {
                   1456:     int                j;
                   1457: 
                   1458:     for (j = 0; j < NG_PPP_MAX_LINKS; j++) {
                   1459:        if (sb->links[j]) {
                   1460:            Printf("%s[%s/%s] ", sb->links[j]->name,
                   1461:                FsmStateName(sb->links[j]->lcp.fsm.state),
                   1462:                gPhysStateNames[sb->links[j]->state]);
                   1463:        }
                   1464:     }
                   1465:     Printf("\r\n");
                   1466: }
                   1467: 
                   1468: /*
                   1469:  * BundFind()
                   1470:  *
                   1471:  * Find a bundle structure
                   1472:  */
                   1473: 
                   1474: Bund
                   1475: BundFind(const char *name)
                   1476: {
                   1477:   int  k;
                   1478: 
                   1479:   for (k = 0;
                   1480:     k < gNumBundles && (!gBundles[k] || strcmp(gBundles[k]->name, name));
                   1481:     k++);
                   1482:   return((k < gNumBundles) ? gBundles[k] : NULL);
                   1483: }
                   1484: 
                   1485: /*
                   1486:  * BundBmStart()
                   1487:  *
                   1488:  * Start bandwidth management timer
                   1489:  */
                   1490: 
                   1491: static void
                   1492: BundBmStart(Bund b)
                   1493: {
                   1494:     int        k;
                   1495: 
                   1496:     /* Reset bandwidth management stats */
                   1497:     memset(&b->bm.traffic, 0, sizeof(b->bm.traffic));
                   1498:     memset(&b->bm.avail, 0, sizeof(b->bm.avail));
                   1499:     memset(&b->bm.wasUp, 0, sizeof(b->bm.wasUp));
                   1500:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1501:        if (b->links[k]) {
                   1502:            memset(&b->links[k]->bm.idleStats,
                   1503:                0, sizeof(b->links[k]->bm.idleStats));
                   1504:        }
                   1505:     }
                   1506: 
                   1507:   /* Start bandwidth management timer */
                   1508:   TimerStop(&b->bm.bmTimer);
                   1509:   if (Enabled(&b->conf.options, BUND_CONF_BWMANAGE)) {
                   1510:     TimerInit(&b->bm.bmTimer, "BundBm",
                   1511:       (b->conf.bm_S * SECONDS) / BUND_BM_N,
                   1512:       BundBmTimeout, b);
                   1513:     TimerStart(&b->bm.bmTimer);
                   1514:   }
                   1515: }
                   1516: 
                   1517: /*
                   1518:  * BundBmStop()
                   1519:  */
                   1520: 
                   1521: static void
                   1522: BundBmStop(Bund b)
                   1523: {
                   1524:   TimerStop(&b->bm.bmTimer);
                   1525: }
                   1526: 
                   1527: /*
                   1528:  * BundBmTimeout()
                   1529:  *
                   1530:  * Do a bandwidth management update
                   1531:  */
                   1532: 
                   1533: static void
                   1534: BundBmTimeout(void *arg)
                   1535: {
                   1536:     Bund               b = (Bund)arg;
                   1537: 
                   1538:     const time_t       now = time(NULL);
                   1539:     u_int              availTotal;
                   1540:     u_int              inUtilTotal = 0, outUtilTotal = 0;
                   1541:     u_int              inBitsTotal, outBitsTotal;
                   1542:     u_int              inUtil[BUND_BM_N];      /* Incoming % utilization */
                   1543:     u_int              outUtil[BUND_BM_N];     /* Outgoing % utilization */
                   1544:     int                        j, k;
                   1545: 
                   1546:     /* Shift and update stats */
                   1547:     memmove(&b->bm.wasUp[1], &b->bm.wasUp[0],
                   1548:        (BUND_BM_N - 1) * sizeof(b->bm.wasUp[0]));
                   1549:     b->bm.wasUp[0] = b->n_up;
                   1550:     memmove(&b->bm.avail[1], &b->bm.avail[0],
                   1551:        (BUND_BM_N - 1) * sizeof(b->bm.avail[0]));
                   1552:     b->bm.avail[0] = b->bm.total_bw;
                   1553: 
                   1554:     /* Shift stats */
                   1555:     memmove(&b->bm.traffic[0][1], &b->bm.traffic[0][0],
                   1556:        (BUND_BM_N - 1) * sizeof(b->bm.traffic[0][0]));
                   1557:     memmove(&b->bm.traffic[1][1], &b->bm.traffic[1][0],
                   1558:        (BUND_BM_N - 1) * sizeof(b->bm.traffic[1][0]));
                   1559:     b->bm.traffic[0][0] = 0;
                   1560:     b->bm.traffic[1][0] = 0;
                   1561:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1562:        if (b->links[k] && b->links[k]->joined_bund) {
                   1563:            Link        const l = b->links[k];
                   1564: 
1.1.1.5 ! misho    1565: #ifndef NG_PPP_STATS64
1.1       misho    1566:            struct ng_ppp_link_stat     oldStats;
1.1.1.5 ! misho    1567: #else
        !          1568:            struct ng_ppp_link_stat64   oldStats;
        !          1569: #endif
1.1       misho    1570:        
                   1571:            /* Get updated link traffic statistics */
                   1572:            oldStats = l->bm.idleStats;
1.1.1.5 ! misho    1573: #ifndef NG_PPP_STATS64
1.1       misho    1574:            NgFuncGetStats(l->bund, l->bundleIndex, &l->bm.idleStats);
1.1.1.5 ! misho    1575: #else
        !          1576:            NgFuncGetStats64(l->bund, l->bundleIndex, &l->bm.idleStats);
        !          1577: #endif
1.1       misho    1578:            b->bm.traffic[0][0] += l->bm.idleStats.recvOctets - oldStats.recvOctets;
                   1579:            b->bm.traffic[1][0] += l->bm.idleStats.xmitOctets - oldStats.xmitOctets;
                   1580:        }
                   1581:     }
                   1582: 
                   1583:     /* Compute utilizations */
                   1584:     memset(&inUtil, 0, sizeof(inUtil));
                   1585:     memset(&outUtil, 0, sizeof(outUtil));
                   1586:     availTotal = inBitsTotal = outBitsTotal = 0;
                   1587:     for (j = 0; j < BUND_BM_N; j++) {
                   1588:        u_int   avail, inBits, outBits;
                   1589: 
                   1590:        avail = (b->bm.avail[j] * b->conf.bm_S) / BUND_BM_N;
                   1591:        inBits = b->bm.traffic[0][j] * 8;
                   1592:        outBits = b->bm.traffic[1][j] * 8;
                   1593: 
                   1594:        availTotal += avail;
                   1595:        inBitsTotal += inBits;
                   1596:        outBitsTotal += outBits;
                   1597: 
                   1598:        /* Compute bandwidth utilizations as percentages */
                   1599:        if (avail != 0) {
                   1600:            inUtil[j] = ((float) inBits / avail) * 100;
                   1601:            outUtil[j] = ((float) outBits / avail) * 100;
                   1602:        }
                   1603:     }
                   1604: 
                   1605:     /* Compute total averaged utilization */
                   1606:     if (availTotal != 0) {
                   1607:        inUtilTotal = ((float) inBitsTotal / availTotal) * 100;
                   1608:        outUtilTotal = ((float) outBitsTotal / availTotal) * 100;
                   1609:     }
                   1610: 
                   1611:   {
                   1612:     char       ins[100], outs[100];
                   1613: 
                   1614:     ins[0] = 0;
                   1615:     for (j = 0; j < BUND_BM_N; j++) {
                   1616:        snprintf(ins + strlen(ins), sizeof(ins) - strlen(ins),
                   1617:                " %3u ", b->bm.wasUp[BUND_BM_N - 1 - j]);
                   1618:     }
                   1619:     Log(LG_BUND2, ("[%s]                       %s", b->name, ins));
                   1620: 
                   1621:     snprintf(ins, sizeof(ins), " IN util: total %3u%%  ", inUtilTotal);
                   1622:     snprintf(outs, sizeof(outs), "OUT util: total %3u%%  ", outUtilTotal);
                   1623:     for (j = 0; j < BUND_BM_N; j++) {
                   1624:       snprintf(ins + strlen(ins), sizeof(ins) - strlen(ins),
                   1625:        " %3u%%", inUtil[BUND_BM_N - 1 - j]);
                   1626:       snprintf(outs + strlen(outs), sizeof(outs) - strlen(outs),
                   1627:        " %3u%%", outUtil[BUND_BM_N - 1 - j]);
                   1628:     }
                   1629:     Log(LG_BUND2, ("[%s] %s", b->name, ins));
                   1630:     Log(LG_BUND2, ("[%s] %s", b->name, outs));
                   1631:   }
                   1632: 
                   1633:   /* See if it's time to bring up another link */
                   1634:   if (now - b->bm.last_open >= b->conf.bm_Mc
                   1635:       && (inUtilTotal >= b->conf.bm_Hi || outUtilTotal >= b->conf.bm_Hi)) {
                   1636:     for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1637: cont:
                   1638:        if (!b->links[k] && b->conf.linkst[k][0])
                   1639:                break;
                   1640:     }
                   1641:     if (k < NG_PPP_MAX_LINKS) {
                   1642:        Log(LG_BUND, ("[%s] opening link \"%s\" due to increased demand",
                   1643:            b->name, b->conf.linkst[k]));
                   1644:        b->bm.last_open = now;
                   1645:        if (b->links[k]) {
                   1646:            RecordLinkUpDownReason(NULL, b->links[k], 1, STR_PORT_NEEDED, NULL);
                   1647:            BundOpenLink(b->links[k]);
                   1648:        } else {
                   1649:            if (BundCreateOpenLink(b, k)) {
                   1650:                if (k < NG_PPP_MAX_LINKS) {
                   1651:                    k++;
                   1652:                    goto cont;
                   1653:                }
                   1654:            } else
                   1655:                RecordLinkUpDownReason(NULL, b->links[k], 1, STR_PORT_NEEDED, NULL);
                   1656:        }
                   1657:     }
                   1658:   }
                   1659: 
                   1660:   /* See if it's time to bring down a link */
                   1661:   if (now - b->bm.last_close >= b->conf.bm_Md
                   1662:       && (inUtilTotal < b->conf.bm_Lo && outUtilTotal < b->conf.bm_Lo)
                   1663:       && b->n_links > 1) {
                   1664:     k = NG_PPP_MAX_LINKS - 1;
                   1665:     while (k >= 0 && (!b->links[k] || !OPEN_STATE(b->links[k]->lcp.fsm.state)))
                   1666:        k--;
                   1667:     assert(k >= 0);
                   1668:     Log(LG_BUND, ("[%s] Bundle: closing link %s due to reduced demand",
                   1669:       b->name, b->links[k]->name));
                   1670:     b->bm.last_close = now;
                   1671:     RecordLinkUpDownReason(NULL, b->links[k], 0, STR_PORT_UNNEEDED, NULL);
                   1672:     BundCloseLink(b->links[k]);
                   1673:   }
                   1674: 
                   1675:   /* Restart timer */
                   1676:   TimerStart(&b->bm.bmTimer);
                   1677: }
                   1678: 
                   1679: /*
                   1680:  * BundNgInit()
                   1681:  *
                   1682:  * Setup the initial PPP netgraph framework. Initializes these fields
                   1683:  * in the supplied bundle structure:
                   1684:  *
                   1685:  *     iface.ifname    - Interface name
                   1686:  *     csock           - Control socket for socket netgraph node
                   1687:  *     dsock           - Data socket for socket netgraph node
                   1688:  *
                   1689:  * Returns -1 if error.
                   1690:  */
                   1691: 
                   1692: static int
                   1693: BundNgInit(Bund b)
                   1694: {
                   1695:     struct ngm_mkpeer  mp;
                   1696:     struct ngm_name    nm;
                   1697:     int                        newIface = 0;
                   1698:     int                        newPpp = 0;
                   1699: 
                   1700:     /* Create new iface node */
                   1701:     if (NgFuncCreateIface(b,
                   1702:        b->iface.ifname, sizeof(b->iface.ifname)) < 0) {
                   1703:       Log(LG_ERR, ("[%s] can't create netgraph interface", b->name));
                   1704:       goto fail;
                   1705:     }
                   1706:     strlcpy(b->iface.ngname, b->iface.ifname, sizeof(b->iface.ngname));
                   1707:     newIface = 1;
                   1708:     b->iface.ifindex = if_nametoindex(b->iface.ifname);
                   1709:     Log(LG_BUND|LG_IFACE, ("[%s] Bundle: Interface %s created",
                   1710:        b->name, b->iface.ifname));
                   1711: 
                   1712:     /* Create new PPP node */
                   1713:     snprintf(b->hook, sizeof(b->hook), "b%d", b->id);
                   1714:     memset(&mp, 0, sizeof(mp));
                   1715:     strcpy(mp.type, NG_PPP_NODE_TYPE);
                   1716:     strcpy(mp.ourhook, b->hook);
                   1717:     strcpy(mp.peerhook, NG_PPP_HOOK_BYPASS);
                   1718:     if (NgSendMsg(gLinksCsock, ".:",
                   1719:            NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                   1720:        Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
                   1721:            b->name, mp.type, ".:", mp.ourhook);
                   1722:        goto fail;
                   1723:     }
                   1724:     newPpp = 1;
                   1725: 
                   1726:     /* Get PPP node ID */
1.1.1.5 ! misho    1727:     if ((b->nodeID = NgGetNodeID(gLinksCsock, b->hook)) == 0) {
        !          1728:        Perror("[%s] Cannot get %s node id", b->name, NG_PPP_NODE_TYPE);
        !          1729:        goto fail;
        !          1730:     }
1.1       misho    1731: 
                   1732:     /* Give it a name */
                   1733:     memset(&nm, 0, sizeof(nm));
                   1734:     snprintf(nm.name, sizeof(nm.name), "mpd%d-%s", gPid, b->name);
                   1735:     if (NgSendMsg(gLinksCsock, b->hook,
                   1736:            NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                   1737:        Perror("[%s] can't name %s node \"%s\"",
                   1738:            b->name, NG_PPP_NODE_TYPE, b->hook);
                   1739:        goto fail;
                   1740:     }
                   1741: 
                   1742:     /* OK */
                   1743:     return(0);
                   1744: 
                   1745: fail:
                   1746:     BundNgShutdown(b, newIface, newPpp);
                   1747:     return(-1);
                   1748: }
                   1749: 
                   1750: /*
                   1751:  * NgFuncShutdown()
                   1752:  */
                   1753: 
                   1754: void
                   1755: BundNgShutdown(Bund b, int iface, int ppp)
                   1756: {
                   1757:     char       path[NG_PATHSIZ];
                   1758: 
                   1759:     if (iface) {
                   1760:        snprintf(path, sizeof(path), "%s:", b->iface.ngname);
                   1761:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   1762:     }
                   1763:     if (ppp) {
                   1764:        snprintf(path, sizeof(path), "[%x]:", b->nodeID);
                   1765:        NgFuncShutdownNode(gLinksCsock, b->name, path);
                   1766:     }
                   1767:     b->hook[0] = 0;
                   1768: }
                   1769: 
                   1770: /*
                   1771:  * BundSetCommand()
                   1772:  */
                   1773: 
                   1774: static int
1.1.1.5 ! misho    1775: BundSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1776: {
                   1777:     Bund       b = ctx->bund;
                   1778:     int                i, val;
                   1779: 
                   1780:     if (ac == 0)
                   1781:        return(-1);
                   1782:     switch ((intptr_t)arg) {
                   1783:        case SET_PERIOD:
                   1784:            b->conf.bm_S = atoi(*av);
                   1785:            break;
                   1786:        case SET_LOW_WATER:
                   1787:            b->conf.bm_Lo = atoi(*av);
                   1788:            break;
                   1789:        case SET_HIGH_WATER:
                   1790:            b->conf.bm_Hi = atoi(*av);
                   1791:            break;
                   1792:        case SET_MIN_CONNECT:
                   1793:            b->conf.bm_Mc = atoi(*av);
                   1794:            break;
                   1795:        case SET_MIN_DISCONNECT:
                   1796:            b->conf.bm_Md = atoi(*av);
                   1797:            break;
                   1798:        case SET_LINKS:
                   1799:            if (ac > NG_PPP_MAX_LINKS)
                   1800:                return (-1);
                   1801:            for (i = 0; i < ac; i++)
                   1802:                strlcpy(b->conf.linkst[i], av[i], LINK_MAX_NAME);
                   1803:            for (; i < NG_PPP_MAX_LINKS; i++)
                   1804:                b->conf.linkst[i][0] = 0;
                   1805:            break;
                   1806: 
                   1807:        case SET_RETRY:
                   1808:            val = atoi(*av);
                   1809:            if (val < 1 || val > 10)
                   1810:                Error("[%s] incorrect fsm-timeout value %d", b->name, val);
                   1811:            else
                   1812:                b->conf.retry_timeout = val;
                   1813:            break;
                   1814: 
                   1815:        case SET_ACCEPT:
                   1816:            AcceptCommand(ac, av, &b->conf.options, gConfList);
                   1817:            break;
                   1818: 
                   1819:        case SET_DENY:
                   1820:            DenyCommand(ac, av, &b->conf.options, gConfList);
                   1821:            break;
                   1822: 
                   1823:        case SET_ENABLE:
                   1824:            EnableCommand(ac, av, &b->conf.options, gConfList);
                   1825:            break;
                   1826: 
                   1827:        case SET_DISABLE:
                   1828:            DisableCommand(ac, av, &b->conf.options, gConfList);
                   1829:            break;
                   1830: 
                   1831:        case SET_YES:
                   1832:            YesCommand(ac, av, &b->conf.options, gConfList);
                   1833:            break;
                   1834: 
                   1835:        case SET_NO:
                   1836:            NoCommand(ac, av, &b->conf.options, gConfList);
                   1837:            break;
                   1838: 
                   1839:        default:
                   1840:            assert(0);
                   1841:     }
                   1842:     return(0);
                   1843: }
                   1844: 

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