File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / bund.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:56:12 2016 UTC (7 years, 8 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p1_cross, v5_8p1, v5_8, HEAD
mpd 5.8

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

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