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

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

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