Annotation of embedaddon/mpd/src/link.c, revision 1.1.1.4.2.1

1.1       misho       1: 
                      2: /*
                      3:  * link.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: 
                     10: #include "ppp.h"
                     11: #include "link.h"
                     12: #include "msg.h"
                     13: #include "lcp.h"
                     14: #include "phys.h"
                     15: #include "command.h"
                     16: #include "input.h"
                     17: #include "ngfunc.h"
                     18: #include "util.h"
                     19: 
                     20: #include <netgraph.h>
                     21: #include <netgraph/ng_message.h>
                     22: #include <netgraph/ng_socket.h>
                     23: #include <netgraph/ng_tee.h>
                     24: 
                     25: /*
                     26:  * DEFINITIONS
                     27:  */
                     28: 
                     29:   /* Set menu options */
                     30:   enum {
                     31:     SET_BUNDLE,
                     32:     SET_FORWARD,
                     33:     SET_DROP,
                     34:     SET_CLEAR,
                     35:     SET_BANDWIDTH,
                     36:     SET_LATENCY,
                     37:     SET_ACCMAP,
                     38:     SET_MRRU,
                     39:     SET_MRU,
                     40:     SET_MTU,
                     41:     SET_FSM_RETRY,
                     42:     SET_MAX_RETRY,
                     43:     SET_RETRY_DELAY,
                     44:     SET_MAX_CHILDREN,
                     45:     SET_KEEPALIVE,
                     46:     SET_IDENT,
                     47:     SET_ACCEPT,
                     48:     SET_DENY,
                     49:     SET_ENABLE,
                     50:     SET_DISABLE,
                     51:     SET_YES,
                     52:     SET_NO
                     53:   };
                     54: 
1.1.1.4.2.1! misho      55:   /* Used to prevent auto-up on links closed manually */
        !            56:   enum {
        !            57:     LINK_ADMINSTATE_DOWN = 0,
        !            58:     LINK_ADMINSTATE_OPERATIONAL
        !            59:   };
        !            60: 
        !            61:   static const char *linkAdminStateNames[] = {
        !            62:     "DOWN",
        !            63:     "OPERATIONAL"
        !            64:   };
        !            65:   
1.1       misho      66:   #define RBUF_SIZE            100
                     67: 
                     68: /*
                     69:  * INTERNAL FUNCTIONS
                     70:  */
                     71: 
1.1.1.4   misho      72:   static int   LinkSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1       misho      73:   static void  LinkMsg(int type, void *cookie);
                     74:   static void  LinkNgDataEvent(int type, void *cookie);
                     75:   static void  LinkReopenTimeout(void *arg);
                     76: 
                     77: /*
                     78:  * GLOBAL VARIABLES
                     79:  */
                     80: 
1.1.1.4   misho      81:   static const struct cmdtab LinkSetActionCmds[] = {
1.1       misho      82:     { "bundle {bundle} [{regex}]",     "Terminate incomings locally",
                     83:        LinkSetCommand, NULL, 2, (void *) SET_BUNDLE },
                     84:     { "forward {link} [{regex}]",      "Forward incomings",
                     85:        LinkSetCommand, NULL, 2, (void *) SET_FORWARD },
                     86:     { "drop [{regex}]",                        "drop incomings",
                     87:        LinkSetCommand, NULL, 2, (void *) SET_DROP },
                     88:     { "clear",                         "Clear actions",
                     89:        LinkSetCommand, NULL, 2, (void *) SET_CLEAR },
1.1.1.4   misho      90:     { NULL, NULL, NULL, NULL, 0, NULL },
1.1       misho      91:   };
                     92: 
                     93:   const struct cmdtab LinkSetCmds[] = {
                     94:     { "action ...",                    "Set action on incoming",
1.1.1.4   misho      95:        CMD_SUBMENU,    NULL, 2, LinkSetActionCmds },
1.1       misho      96:     { "bandwidth {bps}",               "Link bandwidth",
                     97:        LinkSetCommand, NULL, 2, (void *) SET_BANDWIDTH },
                     98:     { "latency {microsecs}",           "Link latency",
                     99:        LinkSetCommand, NULL, 2, (void *) SET_LATENCY },
                    100:     { "accmap {hex-value}",            "Accmap value",
                    101:        LinkSetCommand, NULL, 2, (void *) SET_ACCMAP },
                    102:     { "mrru {value}",                  "Link MRRU value",
                    103:        LinkSetCommand, NULL, 2, (void *) SET_MRRU },
                    104:     { "mru {value}",                   "Link MRU value",
                    105:        LinkSetCommand, NULL, 2, (void *) SET_MRU },
                    106:     { "mtu {value}",                   "Link MTU value",
                    107:        LinkSetCommand, NULL, 2, (void *) SET_MTU },
                    108:     { "fsm-timeout {seconds}",         "FSM retry timeout",
                    109:        LinkSetCommand, NULL, 2, (void *) SET_FSM_RETRY },
                    110:     { "max-redial {num}",              "Max connect attempts",
                    111:        LinkSetCommand, NULL, 2, (void *) SET_MAX_RETRY },
                    112:     { "redial-delay {num}",            "Delay between connect attempts",
                    113:        LinkSetCommand, NULL, 2, (void *) SET_RETRY_DELAY },
                    114:     { "max-children {num}",            "Max number of children",
                    115:        LinkSetCommand, NULL, 2, (void *) SET_MAX_CHILDREN },
                    116:     { "keep-alive {secs} {max}",       "LCP echo keep-alives",
                    117:        LinkSetCommand, NULL, 2, (void *) SET_KEEPALIVE },
                    118:     { "ident {string}",                        "LCP ident string",
                    119:        LinkSetCommand, NULL, 2, (void *) SET_IDENT },
                    120:     { "accept {opt ...}",              "Accept option",
                    121:        LinkSetCommand, NULL, 2, (void *) SET_ACCEPT },
                    122:     { "deny {opt ...}",                        "Deny option",
                    123:        LinkSetCommand, NULL, 2, (void *) SET_DENY },
                    124:     { "enable {opt ...}",              "Enable option",
                    125:        LinkSetCommand, NULL, 2, (void *) SET_ENABLE },
                    126:     { "disable {opt ...}",             "Disable option",
                    127:        LinkSetCommand, NULL, 2, (void *) SET_DISABLE },
                    128:     { "yes {opt ...}",                 "Enable and accept option",
                    129:        LinkSetCommand, NULL, 2, (void *) SET_YES },
                    130:     { "no {opt ...}",                  "Disable and deny option",
                    131:        LinkSetCommand, NULL, 2, (void *) SET_NO },
1.1.1.4   misho     132:     { NULL, NULL, NULL, NULL, 0, NULL },
1.1       misho     133:   };
                    134: 
                    135: /*
                    136:  * INTERNAL VARIABLES
                    137:  */
                    138: 
1.1.1.4   misho     139:   static const struct confinfo gConfList[] = {
1.1       misho     140:     { 0,       LINK_CONF_INCOMING,     "incoming"      },
                    141:     { 1,       LINK_CONF_PAP,          "pap"           },
                    142:     { 1,       LINK_CONF_CHAPMD5,      "chap-md5"      },
                    143:     { 1,       LINK_CONF_CHAPMSv1,     "chap-msv1"     },
                    144:     { 1,       LINK_CONF_CHAPMSv2,     "chap-msv2"     },
                    145:     { 1,       LINK_CONF_EAP,          "eap"           },
                    146:     { 1,       LINK_CONF_ACFCOMP,      "acfcomp"       },
                    147:     { 1,       LINK_CONF_PROTOCOMP,    "protocomp"     },
                    148:     { 0,       LINK_CONF_MSDOMAIN,     "keep-ms-domain"},
                    149:     { 0,       LINK_CONF_MAGICNUM,     "magicnum"      },
                    150:     { 0,       LINK_CONF_PASSIVE,      "passive"       },
                    151:     { 0,       LINK_CONF_CHECK_MAGIC,  "check-magic"   },
                    152:     { 0,       LINK_CONF_NO_ORIG_AUTH, "no-orig-auth"  },
                    153:     { 0,       LINK_CONF_CALLBACK,     "callback"      },
                    154:     { 0,       LINK_CONF_MULTILINK,    "multilink"     },
                    155:     { 1,       LINK_CONF_SHORTSEQ,     "shortseq"      },
                    156:     { 0,       LINK_CONF_TIMEREMAIN,   "time-remain"   },
                    157:     { 0,       LINK_CONF_PEER_AS_CALLING,      "peer-as-calling"       },
                    158:     { 0,       LINK_CONF_REPORT_MAC,   "report-mac"    },
1.1.1.2   misho     159:     { 0,       LINK_CONF_REMOVE_TEE,   "remove-tee"    },
1.1       misho     160:     { 0,       0,                      NULL            },
                    161:   };
                    162: 
                    163:     int                gLinksCsock = -1;               /* Socket node control socket */
                    164:     int                gLinksDsock = -1;               /* Socket node data socket */
1.1.1.4   misho     165:     static EventRef gLinksDataEvent;
1.1       misho     166: 
                    167: int
                    168: LinksInit(void)
                    169: {
                    170:     char       name[NG_NODESIZ];
                    171: 
                    172:     /* Create a netgraph socket node */
                    173:     snprintf(name, sizeof(name), "mpd%d-lso", gPid);
                    174:     if (NgMkSockNode(name, &gLinksCsock, &gLinksDsock) < 0) {
                    175:        Perror("LinksInit(): can't create %s node", NG_SOCKET_NODE_TYPE);
                    176:        return(-1);
                    177:     }
                    178:     (void) fcntl(gLinksCsock, F_SETFD, 1);
                    179:     (void) fcntl(gLinksDsock, F_SETFD, 1);
                    180: 
                    181:     /* Listen for happenings on our node */
                    182:     EventRegister(&gLinksDataEvent, EVENT_READ,
                    183:        gLinksDsock, EVENT_RECURRING, LinkNgDataEvent, NULL);
                    184:        
                    185:     return (0);
                    186: }
                    187: 
                    188: void
                    189: LinksShutdown(void)
                    190: {
                    191:     close(gLinksCsock);
                    192:     gLinksCsock = -1;
                    193:     EventUnRegister(&gLinksDataEvent);
                    194:     close(gLinksDsock);
                    195:     gLinksDsock = -1;
                    196: }
                    197: 
                    198: /*
1.1.1.4.2.1! misho     199:  * LinkOpenAdm()
        !           200:  */
        !           201: 
        !           202: void
        !           203: LinkOpenAdm(Link l)
        !           204: {
        !           205:     l->admin_state = LINK_ADMINSTATE_OPERATIONAL;
        !           206:     RecordLinkUpDownReason(NULL, l, 1, STR_MANUALLY, NULL);
        !           207:     LinkOpen(l);
        !           208: }
        !           209: 
        !           210: /*
1.1       misho     211:  * LinkOpenCmd()
                    212:  */
                    213: 
                    214: int
                    215: LinkOpenCmd(Context ctx)
                    216: {
                    217:     if (ctx->lnk->tmpl)
                    218:        Error("impossible to open template");
1.1.1.4.2.1! misho     219:     LinkOpenAdm(ctx->lnk);
1.1       misho     220:     return (0);
                    221: }
                    222: 
                    223: /*
1.1.1.4.2.1! misho     224:  * LinkCloseAdm()
        !           225:  */
        !           226: 
        !           227: void
        !           228: LinkCloseAdm(Link l)
        !           229: {
        !           230:     l->admin_state = LINK_ADMINSTATE_DOWN;
        !           231:     RecordLinkUpDownReason(NULL, l, 0, STR_MANUALLY, NULL);
        !           232:     LinkClose(l);
        !           233: }
        !           234: 
        !           235: /*
1.1       misho     236:  * LinkCloseCmd()
                    237:  */
                    238: 
                    239: int
                    240: LinkCloseCmd(Context ctx)
                    241: {
                    242:     if (ctx->lnk->tmpl)
                    243:        Error("impossible to close template");
1.1.1.4.2.1! misho     244:     ctx->lnk->admin_state = LINK_ADMINSTATE_DOWN;
1.1       misho     245:     RecordLinkUpDownReason(NULL, ctx->lnk, 0, STR_MANUALLY, NULL);
                    246:     LinkClose(ctx->lnk);
                    247:     return (0);
                    248: }
                    249: 
                    250: /*
                    251:  * LinkOpen()
                    252:  */
                    253: 
                    254: void
                    255: LinkOpen(Link l)
                    256: {
                    257:     REF(l);
                    258:     MsgSend(&l->msgs, MSG_OPEN, l);
                    259: }
                    260: 
                    261: /*
                    262:  * LinkClose()
                    263:  */
                    264: 
                    265: void
                    266: LinkClose(Link l)
                    267: {
                    268:     REF(l);
                    269:     MsgSend(&l->msgs, MSG_CLOSE, l);
                    270: }
                    271: 
                    272: /*
                    273:  * LinkUp()
                    274:  */
                    275: 
                    276: void
                    277: LinkUp(Link l)
                    278: {
                    279:     Log(LG_LINK, ("[%s] Link: UP event", l->name));
                    280: 
                    281:     l->originate = PhysGetOriginate(l);
                    282:     Log(LG_PHYS2, ("[%s] Link: origination is %s",
                    283:        l->name, LINK_ORIGINATION(l->originate)));
                    284:     LcpUp(l);
                    285: }
                    286: 
                    287: /*
                    288:  * LinkDown()
                    289:  */
                    290: 
                    291: void
                    292: LinkDown(Link l)
                    293: {
                    294:     Log(LG_LINK, ("[%s] Link: DOWN event", l->name));
                    295: 
1.1.1.4.2.1! misho     296:     if (OPEN_STATE(l->lcp.fsm.state) || l->admin_state != LINK_ADMINSTATE_DOWN) {
1.1       misho     297:        if (((l->conf.max_redial != 0) && (l->num_redial >= l->conf.max_redial)) ||
                    298:            gShutdownInProgress) {
                    299:            if (l->conf.max_redial >= 0) {
1.1.1.4   misho     300:                Log(LG_LINK, ("[%s] Link: giving up after %hu reconnection attempts",
1.1       misho     301:                  l->name, l->num_redial));
                    302:            }
                    303:            if (!l->stay)
                    304:                l->die = 1;
                    305:            LcpClose(l);
                    306:             LcpDown(l);
                    307:        } else {
                    308:            int delay = l->conf.redial_delay + ((random() ^ l->id ^ gPid) & 3);
                    309: 
                    310:            TimerStop(&l->openTimer);
                    311:            TimerInit(&l->openTimer, "PhysOpen",
                    312:                delay * SECONDS, LinkReopenTimeout, l);
                    313:            TimerStart(&l->openTimer);
                    314: 
                    315:            LcpDown(l);
                    316: 
                    317:            l->num_redial++;
1.1.1.4   misho     318:            Log(LG_LINK, ("[%s] Link: reconnection attempt %hu in %d seconds",
1.1       misho     319:              l->name, l->num_redial, delay));
                    320:        }
                    321:     } else {
                    322:        if (!l->stay)
                    323:            l->die = 1;
                    324:         LcpDown(l);
                    325:     }
                    326: }
                    327: 
                    328: /*
                    329:  * LinkReopenTimeout()
                    330:  */
                    331: 
                    332: static void
                    333: LinkReopenTimeout(void *arg)
                    334: {
                    335:     Link       const l = (Link)arg;
                    336: 
                    337:     if (gShutdownInProgress) {
                    338:        LcpClose(l);
                    339:        return;
                    340:     }
                    341: 
1.1.1.4   misho     342:     Log(LG_LINK, ("[%s] Link: reconnection attempt %hu",
1.1       misho     343:        l->name, l->num_redial));
                    344:     RecordLinkUpDownReason(NULL, l, 1, STR_REDIAL, NULL);
1.1.1.4.2.1! misho     345:     if (!OPEN_STATE(l->lcp.fsm.state))
        !           346:        LinkOpen(l);
1.1       misho     347:     PhysOpen(l);
                    348: }
                    349: 
                    350: /*
                    351:  * LinkMsg()
                    352:  *
                    353:  * Deal with incoming message to this link
                    354:  */
                    355: 
                    356: static void
                    357: LinkMsg(int type, void *arg)
                    358: {
                    359:     Link       l = (Link)arg;
                    360: 
                    361:     if (l->dead) {
                    362:        UNREF(l);
                    363:        return;
                    364:     }
                    365:     Log(LG_LINK, ("[%s] Link: %s event", l->name, MsgName(type)));
                    366:     switch (type) {
                    367:        case MSG_OPEN:
                    368:            l->num_redial = 0;
                    369:            LcpOpen(l);
                    370:            break;
                    371:        case MSG_CLOSE:
                    372:            TimerStop(&l->openTimer);
                    373:            LcpClose(l);
                    374:            break;
                    375:        case MSG_SHUTDOWN:
                    376:            LinkShutdown(l);
                    377:            break;
                    378:        default:
                    379:            assert(FALSE);
                    380:     }
                    381:     UNREF(l);
                    382: }
                    383: 
                    384: /*
                    385:  * LinkCreate()
                    386:  */
                    387: 
                    388: int
1.1.1.4   misho     389: LinkCreate(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     390: {
                    391:     Link       l, lt = NULL;
1.1.1.4   misho     392:     const struct phystype *pt = NULL;
1.1       misho     393:     u_char     tmpl = 0;
                    394:     u_char     stay = 0;
                    395:     int        k;
                    396: 
1.1.1.4   misho     397:     (void)arg;
1.1       misho     398:     RESETREF(ctx->lnk, NULL);
                    399:     RESETREF(ctx->bund, NULL);
                    400:     RESETREF(ctx->rep, NULL);
                    401: 
                    402:     if (ac < 1)
                    403:        return(-1);
                    404: 
                    405:     if (strcmp(av[0], "template") == 0) {
                    406:        tmpl = 1;
                    407:        stay = 1;
                    408:     } else if (strcmp(av[0], "static") == 0)
                    409:        stay = 1;
                    410: 
                    411:     if (ac != stay + 2)
                    412:        return(-1);
                    413: 
                    414:     if (strlen(av[0 + stay]) >= (LINK_MAX_NAME - tmpl * 5))
                    415:        Error("Link name \"%s\" is too long", av[0 + stay]);
                    416: 
                    417:     /* See if link name already taken */
                    418:     if ((l = LinkFind(av[0 + stay])) != NULL)
                    419:        Error("Link \"%s\" already exists", av[0 + stay]);
                    420: 
                    421:     for (k = 0; (pt = gPhysTypes[k]); k++) {
                    422:         if (!strcmp(pt->name, av[0 + stay]))
                    423:            Error("Name \"%s\" is reserved by device type", av[0 + stay]);
                    424:     }
                    425: 
                    426:     /* Locate type */
                    427:     for (k = 0; (pt = gPhysTypes[k]); k++) {
                    428:         if (!strcmp(pt->name, av[1 + stay]))
                    429:            break;
                    430:     }
                    431:     if (pt != NULL) {
                    432:         if (!pt->tmpl && tmpl)
                    433:            Error("Link type \"%s\" does not support templating", av[1 + stay]);
                    434: 
                    435:     } else {
                    436:         /* See if template name specified */
                    437:        if ((lt = LinkFind(av[1 + stay])) == NULL)
                    438:            Error("Link template \"%s\" not found", av[1 + tmpl]);
                    439:        if (!lt->tmpl)
                    440:            Error("Link \"%s\" is not a template", av[1 + stay]);
                    441:     }
                    442: 
                    443:     /* Create and initialize new link */
                    444:     if (lt) {
                    445:        l = LinkInst(lt, av[0 + stay], tmpl, stay);
                    446:     } else {
                    447:        l = Malloc(MB_LINK, sizeof(*l));
                    448:        strlcpy(l->name, av[0 + stay], sizeof(l->name));
                    449:        l->type = pt;
                    450:        l->tmpl = tmpl;
1.1.1.4.2.1! misho     451:        l->admin_state = LINK_ADMINSTATE_OPERATIONAL;
1.1       misho     452:        l->stay = stay;
                    453:        l->parent = -1;
                    454:        SLIST_INIT(&l->actions);
                    455: 
                    456:        /* Initialize link configuration with defaults */
                    457:        l->conf.mru = LCP_DEFAULT_MRU;
1.1.1.4.2.1! misho     458:        /* Do not assume any MTU value for this moment */
        !           459:        l->conf.mtu = 0;
1.1       misho     460:        l->conf.mrru = MP_DEFAULT_MRRU;
                    461:         l->conf.accmap = 0x000a0000;
                    462:         l->conf.max_redial = -1;
                    463:         l->conf.redial_delay = 1;
                    464:         l->conf.retry_timeout = LINK_DEFAULT_RETRY;
                    465:        l->conf.max_children = 10000;
                    466:         l->bandwidth = LINK_DEFAULT_BANDWIDTH;
                    467:         l->latency = LINK_DEFAULT_LATENCY;
                    468:         l->upReason = NULL;
                    469:         l->upReasonValid = 0;
                    470:         l->downReason = NULL;
                    471:         l->downReasonValid = 0;
1.1.1.2   misho     472:         l->tee_removed = 0;
1.1       misho     473: 
                    474:         Disable(&l->conf.options, LINK_CONF_CHAPMD5);
                    475:         Accept(&l->conf.options, LINK_CONF_CHAPMD5);
                    476: 
                    477:         Disable(&l->conf.options, LINK_CONF_CHAPMSv1);
                    478:         Deny(&l->conf.options, LINK_CONF_CHAPMSv1);
                    479: 
                    480:         Disable(&l->conf.options, LINK_CONF_CHAPMSv2);
                    481:         Accept(&l->conf.options, LINK_CONF_CHAPMSv2);
                    482: 
                    483:         Disable(&l->conf.options, LINK_CONF_PAP);
                    484:        Accept(&l->conf.options, LINK_CONF_PAP);
                    485: 
                    486:         Disable(&l->conf.options, LINK_CONF_EAP);
                    487:         Accept(&l->conf.options, LINK_CONF_EAP);
                    488: 
                    489:         Disable(&l->conf.options, LINK_CONF_MSDOMAIN);
                    490: 
                    491:         Enable(&l->conf.options, LINK_CONF_ACFCOMP);
                    492:         Accept(&l->conf.options, LINK_CONF_ACFCOMP);
                    493: 
                    494:         Enable(&l->conf.options, LINK_CONF_PROTOCOMP);
                    495:         Accept(&l->conf.options, LINK_CONF_PROTOCOMP);
                    496: 
                    497:         Enable(&l->conf.options, LINK_CONF_MAGICNUM);
                    498:         Disable(&l->conf.options, LINK_CONF_PASSIVE);
                    499:         Enable(&l->conf.options, LINK_CONF_CHECK_MAGIC);
                    500: 
                    501:        Disable(&l->conf.options, LINK_CONF_MULTILINK);
                    502:        Enable(&l->conf.options, LINK_CONF_SHORTSEQ);
                    503:        Accept(&l->conf.options, LINK_CONF_SHORTSEQ);
                    504: 
                    505:         PhysInit(l);
                    506:         LcpInit(l);
                    507:        
                    508:        MsgRegister(&l->msgs, LinkMsg);
                    509: 
                    510:        /* Find a free link pointer */
                    511:         for (k = 0; k < gNumLinks && gLinks[k] != NULL; k++);
                    512:         if (k == gNumLinks)                    /* add a new link pointer */
                    513:            LengthenArray(&gLinks, sizeof(*gLinks), &gNumLinks, MB_LINK);
                    514:            
                    515:        l->id = k;
                    516:        gLinks[k] = l;
                    517:        REF(l);
                    518:     }
                    519: 
                    520:     RESETREF(ctx->lnk, l);
                    521: 
                    522:     return (0);
                    523: }
                    524: 
                    525: /*
                    526:  * LinkDestroy()
                    527:  */
                    528: 
                    529: int
1.1.1.4   misho     530: LinkDestroy(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     531: {
                    532:     Link       l;
                    533: 
1.1.1.4   misho     534:     (void)arg;
1.1       misho     535:     if (ac > 1)
                    536:        return(-1);
                    537: 
                    538:     if (ac == 1) {
                    539:        if ((l = LinkFind(av[0])) == NULL)
                    540:            Error("Link \"%s\" not found", av[0]);
                    541:     } else {
                    542:        if (ctx->lnk) {
                    543:            l = ctx->lnk;
                    544:        } else
                    545:            Error("No link selected to destroy");
                    546:     }
                    547:     
                    548:     if (l->tmpl) {
                    549:        l->tmpl = 0;
                    550:        l->stay = 0;
                    551:        LinkShutdown(l);
                    552:     } else {
                    553:        l->stay = 0;
                    554:        if (l->rep) {
                    555:            PhysClose(l);
                    556:        } else if (OPEN_STATE(l->lcp.fsm.state)) {
                    557:            LcpClose(l);
                    558:        } else {
                    559:            l->die = 1; /* Hack! We should do it as we changed l->stay */
                    560:            LinkShutdownCheck(l, l->lcp.fsm.state);
                    561:        }
                    562:     }
                    563: 
                    564:     return (0);
                    565: }
                    566: 
                    567: /*
                    568:  * LinkInst()
                    569:  */
                    570: 
                    571: Link
1.1.1.4   misho     572: LinkInst(Link lt, const char *name, int tmpl, int stay)
1.1       misho     573: {
                    574:     Link       l;
                    575:     int                k;
                    576:     struct linkaction  *a, *ap, *at;
                    577: 
                    578:     /* Create and initialize new link */
                    579:     l = Mdup(MB_LINK, lt, sizeof(*l));
                    580:     
                    581:     ap = NULL;
                    582:     SLIST_INIT(&l->actions);
                    583:     SLIST_FOREACH(at, &lt->actions, next) {
                    584:        a = Mdup(MB_AUTH, at, sizeof(*a));
                    585:        if (a->regex[0])
                    586:            regcomp(&a->regexp, a->regex, REG_EXTENDED);
                    587:        if (!ap)
                    588:            SLIST_INSERT_HEAD(&l->actions, a, next);
                    589:        else
                    590:            SLIST_INSERT_AFTER(ap, a, next);
                    591:        ap = a;
                    592:     }
1.1.1.4.2.1! misho     593:     l->admin_state = LINK_ADMINSTATE_OPERATIONAL;
1.1       misho     594:     l->tmpl = tmpl;
                    595:     l->stay = stay;
                    596:     /* Count link as one more child of parent. */
                    597:     gChildren++;
                    598:     lt->children++;
                    599:     l->parent = lt->id;
                    600:     l->children = 0;
                    601:     l->refs = 0;
                    602: 
                    603:     /* Find a free link pointer */
                    604:     for (k = 0; k < gNumLinks && gLinks[k] != NULL; k++);
                    605:     if (k == gNumLinks)                        /* add a new link pointer */
                    606:        LengthenArray(&gLinks, sizeof(*gLinks), &gNumLinks, MB_LINK);
                    607: 
                    608:     l->id = k;
                    609: 
                    610:     if (name)
                    611:        strlcpy(l->name, name, sizeof(l->name));
                    612:     else
                    613:        snprintf(l->name, sizeof(l->name), "%s-%d", lt->name, k);
                    614:     gLinks[k] = l;
                    615:     REF(l);
                    616: 
                    617:     PhysInst(l, lt);
                    618:     LcpInst(l, lt);
                    619: 
                    620:     return (l);
                    621: }
                    622: 
                    623: void
                    624: LinkShutdownCheck(Link l, short state)
                    625: {
                    626:     if (state == ST_INITIAL && l->lcp.auth.acct_thread == NULL &&
                    627:            l->die && !l->stay && l->state == PHYS_STATE_DOWN) {
                    628:        REF(l);
                    629:        MsgSend(&l->msgs, MSG_SHUTDOWN, l);
                    630:     }
                    631: }
                    632: 
                    633: /*
                    634:  * LinkShutdown()
                    635:  *
                    636:  */
                    637: 
                    638: void
                    639: LinkShutdown(Link l)
                    640: {
                    641:     struct linkaction  *a;
                    642: 
                    643:     Log(LG_LINK, ("[%s] Link: Shutdown", l->name));
                    644: 
                    645:     /* Late divorce for DoD case */
                    646:     if (l->bund) {
                    647:        l->bund->links[l->bundleIndex] = NULL;
                    648:        l->bund->n_links--;
                    649:        l->bund = NULL;
                    650:     }
                    651:     gLinks[l->id] = NULL;
                    652:     /* Our parent lost one children */
                    653:     if (l->parent >= 0) {
                    654:        gChildren--;
                    655:        gLinks[l->parent]->children--;
                    656:     }
                    657:     /* Our children are orphans */
                    658:     if (l->children) {
                    659:        int k;
                    660:        for (k = 0; k < gNumLinks; k++) {
                    661:            if (gLinks[k] && gLinks[k]->parent == l->id)
                    662:                gLinks[k]->parent = -1;
                    663:        }
                    664:     }
                    665:     MsgUnRegister(&l->msgs);
                    666:     if (l->hook[0])
                    667:        LinkNgShutdown(l);
                    668:     PhysShutdown(l);
                    669:     LcpShutdown(l);
                    670:     l->dead = 1;
                    671:     while ((a = SLIST_FIRST(&l->actions)) != NULL) {
                    672:        SLIST_REMOVE_HEAD(&l->actions, next);
                    673:        if (a->regex[0])
                    674:            regfree(&a->regexp);
                    675:        Freee(a);
                    676:     }
                    677:     if (l->upReason)
                    678:        Freee(l->upReason);
                    679:     if (l->downReason)
                    680:        Freee(l->downReason);
                    681:     MsgUnRegister(&l->msgs);
                    682:     UNREF(l);
                    683:     CheckOneShot();
                    684: }
                    685: 
                    686: /*
                    687:  * LinkNgInit()
                    688:  *
                    689:  * Setup the initial link framework.
                    690:  *
                    691:  * Returns -1 if error.
                    692:  */
                    693: 
                    694: int
                    695: LinkNgInit(Link l)
                    696: {
                    697:     struct ngm_mkpeer  mp;
                    698:     struct ngm_name    nm;
                    699: 
                    700:     /* Initialize structures */
                    701:     memset(&mp, 0, sizeof(mp));
                    702:     memset(&nm, 0, sizeof(nm));
                    703: 
                    704:     /* Create TEE node */
                    705:     strcpy(mp.type, NG_TEE_NODE_TYPE);
                    706:     snprintf(mp.ourhook, sizeof(mp.ourhook), "l%d", l->id);
                    707:     strcpy(mp.peerhook, NG_TEE_HOOK_LEFT2RIGHT);
                    708:     if (NgSendMsg(gLinksCsock, ".:",
                    709:       NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
                    710:        Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
                    711:            l->name, mp.type, ".:", mp.ourhook);
                    712:        goto fail;
                    713:     }
                    714:     strlcpy(l->hook, mp.ourhook, sizeof(l->hook));
                    715: 
                    716:     /* Give it a name */
                    717:     snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-lt", gPid, l->name);
                    718:     if (NgSendMsg(gLinksCsock, l->hook,
                    719:       NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
                    720:        Perror("[%s] can't name %s node \"%s\"",
                    721:            l->name, NG_TEE_NODE_TYPE, l->hook);
                    722:        goto fail;
                    723:     }
                    724: 
                    725:     /* Get TEE node ID */
                    726:     if ((l->nodeID = NgGetNodeID(gLinksCsock, l->hook)) == 0) {
                    727:        Perror("[%s] Cannot get %s node id", l->name, NG_TEE_NODE_TYPE);
                    728:        goto fail;
                    729:     };
                    730: 
                    731:     /* OK */
                    732:     return(0);
                    733: 
                    734: fail:
                    735:     LinkNgShutdown(l);
                    736:     return(-1);
                    737: }
                    738: 
                    739: /*
                    740:  * LinkNgJoin()
                    741:  */
                    742: 
                    743: int
                    744: LinkNgJoin(Link l)
                    745: {
                    746:     char               path[NG_PATHSIZ];
                    747:     struct ngm_connect cn;
                    748: 
                    749:     snprintf(path, sizeof(path), "[%lx]:", (u_long)l->nodeID);
                    750: 
                    751:     memset(&cn, 0, sizeof(cn));
                    752:     snprintf(cn.path, sizeof(cn.path), "[%lx]:", (u_long)l->bund->nodeID);
                    753:     strcpy(cn.ourhook, NG_TEE_HOOK_RIGHT);
                    754:     snprintf(cn.peerhook, sizeof(cn.peerhook), "%s%d", 
                    755:        NG_PPP_HOOK_LINK_PREFIX, l->bundleIndex);
                    756:     if (NgSendMsg(gLinksCsock, path,
                    757:       NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    758:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    759:            l->name, path, cn.ourhook, cn.path, cn.peerhook);
                    760:        return(-1);
                    761:     }
                    762:     
                    763:     NgFuncDisconnect(gLinksCsock, l->name, path, NG_TEE_HOOK_LEFT2RIGHT);
1.1.1.2   misho     764: 
                    765:     if (Enabled(&l->conf.options, LINK_CONF_REMOVE_TEE)) {
                    766:        if (l->stay == 0) {
                    767:            Log(LG_LINK, ("[%s] Link: Removing ng_tee node", l->name));
                    768:            NgFuncShutdownNode(gLinksCsock, NG_TEE_NODE_TYPE, path);
                    769:            l->tee_removed = 1;
                    770:        } else
                    771:            Log(LG_LINK, ("[%s] Link: Can't remove ng_tee node on static link",
                    772:            l->name));
                    773:     }
1.1       misho     774:     return (0);
                    775: }
                    776: 
                    777: /*
                    778:  * LinkNgLeave()
                    779:  */
                    780: 
                    781: int
                    782: LinkNgLeave(Link l)
                    783: {
                    784:     char               path[NG_PATHSIZ];
                    785:     struct ngm_connect cn;
                    786: 
1.1.1.2   misho     787:     /* ng_tee is already removed */
                    788:     if (l->tee_removed == 1)
                    789:        return(0);
                    790: 
1.1       misho     791:     memset(&cn, 0, sizeof(cn));
                    792:     snprintf(cn.path, sizeof(cn.path), "[%lx]:", (u_long)l->nodeID);
                    793:     strcpy(cn.ourhook, l->hook);
                    794:     strcpy(cn.peerhook, NG_TEE_HOOK_LEFT2RIGHT);
                    795:     if (NgSendMsg(gLinksCsock, ".:",
                    796:       NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    797:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    798:            l->name, ".:", cn.ourhook, cn.path, cn.peerhook);
                    799:        return(-1);
                    800:     }
                    801: 
                    802:     snprintf(path, sizeof(path), "[%lx]:", (u_long)l->nodeID);
                    803:     NgFuncDisconnect(gLinksCsock, l->name, path, NG_TEE_HOOK_RIGHT);
                    804:     return (0);
                    805: }
                    806: 
                    807: /*
                    808:  * LinkNgToRep()
                    809:  */
                    810: 
                    811: int
                    812: LinkNgToRep(Link l)
                    813: {
                    814:     char               path[NG_PATHSIZ];
                    815:     struct ngm_connect cn;
                    816: 
                    817:     /* Connect link to repeater */
                    818:     snprintf(path, sizeof(path), "[%lx]:", (u_long)l->nodeID);
                    819:     strcpy(cn.ourhook, NG_TEE_HOOK_RIGHT);
                    820:     if (!PhysGetUpperHook(l, cn.path, cn.peerhook)) {
                    821:         Log(LG_PHYS, ("[%s] Link: can't get repeater hook", l->name));
                    822:         return (-1);
                    823:     }
                    824:     if (NgSendMsg(gLinksCsock, path,
                    825:       NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    826:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    827:            l->name, path, cn.ourhook, cn.path, cn.peerhook);
                    828:        return(-1);
                    829:     }
                    830: 
                    831:     /* Shutdown link tee node */
                    832:     NgFuncShutdownNode(gLinksCsock, l->name, path);
                    833:     l->hook[0] = 0;
                    834:     return (0);
                    835: }
                    836: 
                    837: /*
                    838:  * LinkNgShutdown()
                    839:  */
                    840: 
                    841: void
                    842: LinkNgShutdown(Link l)
                    843: {
                    844:     if (l->hook[0])
                    845:        NgFuncShutdownNode(gLinksCsock, l->name, l->hook);
                    846:     l->hook[0] = 0;
                    847: }
                    848: 
                    849: /*
                    850:  * LinkNgDataEvent()
                    851:  */
                    852: 
                    853: static void
                    854: LinkNgDataEvent(int type, void *cookie)
                    855: {
                    856:     Link               l;
                    857:     Bund               b;
                    858:     u_char             *buf;
                    859:     u_int16_t          proto;
1.1.1.4   misho     860:     unsigned           ptr;
1.1       misho     861:     Mbuf               bp;
                    862:     struct sockaddr_ng naddr;
                    863:     socklen_t          nsize;
                    864:     char               *name, *rest;
                    865:     int                        id, num = 0;
                    866: 
1.1.1.4   misho     867:     (void)cookie;
                    868:     (void)type;
                    869: 
1.1       misho     870:     /* Read all available packets */
                    871:     while (1) {
                    872:        if (num > 20)
                    873:            return;
                    874:        bp = mballoc(4096);
                    875:        buf = MBDATA(bp);
                    876:        /* Read data */
                    877:        nsize = sizeof(naddr);
                    878:        if ((bp->cnt = recvfrom(gLinksDsock, buf, MBSPACE(bp), MSG_DONTWAIT, (struct sockaddr *)&naddr, &nsize)) < 0) {
                    879:            mbfree(bp);
                    880:            if (errno == EAGAIN)
                    881:                return;
1.1.1.2   misho     882:            Perror("Link: Link socket read error");
1.1       misho     883:            return;
                    884:        }
                    885:        num++;
                    886: 
                    887:        name = naddr.sg_data;
                    888:        switch (name[0]) {
                    889:        case 'l':
                    890:            name++;
                    891:            id = strtol(name, &rest, 10);
                    892:            if (rest[0] != 0 || !gLinks[id]) {
1.1.1.2   misho     893:                Log(LG_ERR, ("Link: Packet from unexisting link \"%s\"",
1.1       misho     894:                    name));
                    895:                mbfree(bp);
                    896:                continue;
                    897:            }
                    898:            if (gLinks[id]->dead) {
                    899:                Log(LG_LINK, ("Link: Packet from dead link \"%s\"", name));
                    900:                mbfree(bp);
                    901:                continue;
                    902:            }
                    903:            l = gLinks[id];
                    904: 
                    905:            /* Extract protocol */
                    906:            ptr = 0;
                    907:            if ((buf[0] == 0xff) && (buf[1] == 0x03))
                    908:                ptr = 2;
                    909:            proto = buf[ptr++];
                    910:            if ((proto & 0x01) == 0)
                    911:                proto = (proto << 8) + buf[ptr++];
                    912: 
                    913:            if (MBLEN(bp) <= ptr) {
                    914:                LogDumpBp(LG_FRAME|LG_ERR, bp,
1.1.1.2   misho     915:                    "[%s] rec'd truncated %zu bytes frame from link",
1.1       misho     916:                    l->name, MBLEN(bp));
                    917:                mbfree(bp);
                    918:                continue;
                    919:            }
                    920: 
                    921:            /* Debugging */
                    922:            LogDumpBp(LG_FRAME, bp,
1.1.1.2   misho     923:                "[%s] rec'd %zu bytes frame from link proto=0x%04x",
1.1       misho     924:                l->name, MBLEN(bp), proto);
                    925:       
                    926:            bp = mbadj(bp, ptr);
                    927: 
                    928:            /* Input frame */
                    929:            InputFrame(l->bund, l, proto, bp);
                    930:            break;
                    931:        case 'b':
                    932:        case 'i':
                    933:        case 'o':
                    934:        case '4':
                    935:        case '6':
                    936:            name++;
                    937:            id = strtol(name, &rest, 10);
                    938:            if (rest[0] != 0 || !gBundles[id]) {
                    939:                Log(LG_ERR, ("Link: Packet from unexisting bundle \"%s\"",
                    940:                    name));
                    941:                mbfree(bp);
                    942:                continue;
                    943:            }
                    944:            if (gBundles[id]->dead) {
                    945:                Log(LG_LINK, ("Link: Packet from dead bundle \"%s\"", name));
                    946:                mbfree(bp);
                    947:                continue;
                    948:            }
                    949:            b = gBundles[id];
                    950: 
                    951:            /* A PPP frame from the bypass hook? */
                    952:            if (naddr.sg_data[0] == 'b') {
1.1.1.4   misho     953:                Link            ll;
                    954:                u_int16_t       linkNum, lproto;
1.1       misho     955: 
                    956:                if (MBLEN(bp) <= 4) {
                    957:                    LogDumpBp(LG_FRAME|LG_ERR, bp,
1.1.1.2   misho     958:                        "[%s] rec'd truncated %zu bytes frame",
1.1       misho     959:                        b->name, MBLEN(bp));
                    960:                    continue;
                    961:                }
                    962: 
                    963:                /* Extract link number and protocol */
                    964:                bp = mbread(bp, &linkNum, 2);
                    965:                linkNum = ntohs(linkNum);
1.1.1.4   misho     966:                bp = mbread(bp, &lproto, 2);
                    967:                lproto = ntohs(lproto);
1.1       misho     968: 
                    969:                /* Debugging */
                    970:                LogDumpBp(LG_FRAME, bp,
1.1.1.2   misho     971:                    "[%s] rec'd %zu bytes bypass frame link=%d proto=0x%04x",
1.1.1.4   misho     972:                    b->name, MBLEN(bp), (int16_t)linkNum, lproto);
1.1       misho     973: 
                    974:                /* Set link */
                    975:                assert(linkNum == NG_PPP_BUNDLE_LINKNUM || linkNum < NG_PPP_MAX_LINKS);
                    976: 
                    977:                if (linkNum != NG_PPP_BUNDLE_LINKNUM)
1.1.1.4   misho     978:                    ll = b->links[linkNum];
1.1       misho     979:                else
1.1.1.4   misho     980:                    ll = NULL;
1.1       misho     981: 
1.1.1.4   misho     982:                InputFrame(b, ll, lproto, bp);
1.1       misho     983:                continue;
                    984:            }
                    985: 
                    986:            /* Debugging */
                    987:            LogDumpBp(LG_FRAME, bp,
1.1.1.2   misho     988:                "[%s] rec'd %zu bytes frame on %s hook", b->name, MBLEN(bp), naddr.sg_data);
1.1       misho     989: 
                    990: #ifndef USE_NG_TCPMSS
                    991:            /* A snooped, outgoing TCP SYN frame */
                    992:            if (naddr.sg_data[0] == 'o') {
                    993:                IfaceCorrectMSS(bp, MAXMSS(b->iface.mtu));
                    994:                naddr.sg_data[0] = 'i';
                    995:                NgFuncWriteFrame(gLinksDsock, naddr.sg_data, b->name, bp);
                    996:                continue;
                    997:            }
                    998: 
                    999:            /* A snooped, incoming TCP SYN frame */
                   1000:            if (naddr.sg_data[0] == 'i') {
                   1001:                IfaceCorrectMSS(bp, MAXMSS(b->iface.mtu));
                   1002:                naddr.sg_data[0] = 'o';
                   1003:                NgFuncWriteFrame(gLinksDsock, naddr.sg_data, b->name, bp);
                   1004:                continue;
                   1005:            }
                   1006: #endif
                   1007: 
                   1008:            /* A snooped, outgoing IP frame */
                   1009:            if (naddr.sg_data[0] == '4') {
                   1010:                IfaceListenInput(b, PROTO_IP, bp);
                   1011:                continue;
                   1012:            }
                   1013: 
                   1014:            /* A snooped, outgoing IPv6 frame */
                   1015:            if (naddr.sg_data[0] == '6') {
                   1016:                IfaceListenInput(b, PROTO_IPV6, bp);
                   1017:                continue;
                   1018:            }
                   1019: 
                   1020:            break;
                   1021:        default:
                   1022:            Log(LG_ERR, ("Link: Packet from unknown hook \"%s\"",
                   1023:                name));
                   1024:            mbfree(bp);
                   1025:        }
                   1026:     }
                   1027: }
                   1028: 
                   1029: /*
                   1030:  * LinkFind()
                   1031:  *
                   1032:  * Find a link structure
                   1033:  */
                   1034: 
                   1035: Link
                   1036: LinkFind(const char *name)
                   1037: {
                   1038:     int                k;
                   1039: 
                   1040:     k = gNumLinks;
                   1041:     if ((sscanf(name, "[%x]", &k) != 1) || (k < 0) || (k >= gNumLinks)) {
                   1042:         /* Find link */
                   1043:        for (k = 0;
                   1044:            k < gNumLinks && (gLinks[k] == NULL ||
                   1045:                strcmp(gLinks[k]->name, name));
                   1046:            k++);
                   1047:     };
                   1048:     if (k == gNumLinks) {
                   1049:        return (NULL);
                   1050:     }
                   1051: 
                   1052:     return (gLinks[k]);
                   1053: }
                   1054: 
                   1055: /*
                   1056:  * LinkCommand()
                   1057:  */
                   1058: 
                   1059: int
1.1.1.4   misho    1060: LinkCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1061: {
                   1062:     Link       l;
                   1063:     int                k;
                   1064: 
1.1.1.4   misho    1065:     (void)arg;
1.1       misho    1066:     if (ac > 1)
                   1067:        return (-1);
                   1068: 
                   1069:     if (ac == 0) {
                   1070:         Printf("Defined links:\r\n");
                   1071:         for (k = 0; k < gNumLinks; k++) {
                   1072:            if ((l = gLinks[k]) != NULL) {
                   1073:                if (l && l->bund)
                   1074:                    Printf("\t%-15s%s\r\n", 
                   1075:                        l->name, l->bund->name);
                   1076:                else if (l->rep)
                   1077:                    Printf("\t%-15s%s\r\n",
                   1078:                         l->name, l->rep->name);
                   1079:                else
                   1080:                    Printf("\t%s\r\n", 
                   1081:                        l->name);
                   1082:            }
                   1083:        }
                   1084:        return (0);
                   1085:     }
                   1086: 
                   1087:     if ((l = LinkFind(av[0])) == NULL) {
                   1088:         RESETREF(ctx->lnk, NULL);
                   1089:         RESETREF(ctx->bund, NULL);
                   1090:         RESETREF(ctx->rep, NULL);
                   1091:        Error("Link \"%s\" is not defined", av[0]);
                   1092:     }
                   1093: 
                   1094:     /* Change default link and bundle */
                   1095:     RESETREF(ctx->lnk, l);
                   1096:     RESETREF(ctx->bund, l->bund);
                   1097:     RESETREF(ctx->rep, NULL);
                   1098: 
                   1099:     return(0);
                   1100: }
                   1101: 
                   1102: /*
                   1103:  * SessionCommand()
                   1104:  */
                   1105: 
                   1106: int
1.1.1.4   misho    1107: SessionCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1108: {
                   1109:     int                k;
                   1110: 
1.1.1.4   misho    1111:     (void)arg;
1.1       misho    1112:     if (ac > 1)
                   1113:        return (-1);
                   1114: 
                   1115:     if (ac == 0) {
                   1116:        Printf("Present sessions:\r\n");
                   1117:        for (k = 0; k < gNumLinks; k++) {
                   1118:            if (gLinks[k] && gLinks[k]->session_id[0])
                   1119:                Printf("\t%s\r\n", gLinks[k]->session_id);
                   1120:        }
                   1121:        return (0);
                   1122:     }
                   1123: 
                   1124:     /* Find link */
                   1125:     for (k = 0;
                   1126:        k < gNumLinks && (gLinks[k] == NULL || 
                   1127:            strcmp(gLinks[k]->session_id, av[0]));
                   1128:        k++);
                   1129:     if (k == gNumLinks) {
                   1130:        /* Change default link and bundle */
                   1131:        RESETREF(ctx->lnk, NULL);
                   1132:        RESETREF(ctx->bund, NULL);
                   1133:        RESETREF(ctx->rep, NULL);
                   1134:        Error("Session \"%s\" is not found", av[0]);
                   1135:     }
                   1136: 
                   1137:     /* Change default link and bundle */
                   1138:     RESETREF(ctx->lnk, gLinks[k]);
                   1139:     RESETREF(ctx->bund, ctx->lnk->bund);
                   1140:     RESETREF(ctx->rep, NULL);
                   1141: 
                   1142:     return(0);
                   1143: }
                   1144: 
                   1145: /*
                   1146:  * AuthnameCommand()
                   1147:  */
                   1148: 
                   1149: int
1.1.1.4   misho    1150: AuthnameCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1151: {
                   1152:     int                k;
                   1153: 
1.1.1.4   misho    1154:     (void)arg;
1.1.1.2   misho    1155:     if (ac > 2)
1.1       misho    1156:        return (-1);
                   1157: 
                   1158:     if (ac == 0) {
                   1159:        Printf("Present users:\r\n");
                   1160:        for (k = 0; k < gNumLinks; k++) {
                   1161:            if (gLinks[k] && gLinks[k]->lcp.auth.params.authname[0])
                   1162:                Printf("\t%s\r\n", gLinks[k]->lcp.auth.params.authname);
                   1163:        }
                   1164:        return (0);
                   1165:     }
                   1166: 
1.1.1.2   misho    1167:     if (ac == 2 && strcasecmp(av[1], "ci") == 0) {
                   1168:        /* Find link */
                   1169:        for (k = 0;
                   1170:            k < gNumLinks && (gLinks[k] == NULL || 
                   1171:                strcasecmp(gLinks[k]->lcp.auth.params.authname, av[0]));
                   1172:            k++);
                   1173:     } else {
                   1174:        /* Find link */
                   1175:        for (k = 0;
                   1176:            k < gNumLinks && (gLinks[k] == NULL || 
                   1177:                strcmp(gLinks[k]->lcp.auth.params.authname, av[0]));
                   1178:            k++);
                   1179:     }
1.1       misho    1180:     if (k == gNumLinks) {
                   1181:        /* Change default link and bundle */
                   1182:        RESETREF(ctx->lnk, NULL);
                   1183:        RESETREF(ctx->bund, NULL);
                   1184:        RESETREF(ctx->rep, NULL);
                   1185:        Error("User \"%s\" is not found", av[0]);
                   1186:     }
                   1187: 
                   1188:     /* Change default link and bundle */
                   1189:     RESETREF(ctx->lnk, gLinks[k]);
                   1190:     RESETREF(ctx->bund, ctx->lnk->bund);
                   1191:     RESETREF(ctx->rep, NULL);
                   1192: 
                   1193:     return(0);
                   1194: }
                   1195: 
                   1196: /*
                   1197:  * RecordLinkUpDownReason()
                   1198:  *
                   1199:  * This is called whenever a reason for the link going up or
                   1200:  * down has just become known. Record this reason so that when
                   1201:  * the link actually goes up or down, we can record it.
                   1202:  *
                   1203:  * If this gets called more than once in the "down" case,
                   1204:  * the first call prevails.
                   1205:  */
                   1206: static void
                   1207: RecordLinkUpDownReason2(Link l, int up, const char *key, const char *fmt, va_list args)
                   1208: {
                   1209:     char       **const cpp = up ? &l->upReason : &l->downReason;
                   1210:     char       *buf;
                   1211: 
                   1212:     /* First reason overrides later ones */
                   1213:     if (up) {
                   1214:        if (l->upReasonValid) {
                   1215:            return;
                   1216:        } else {
                   1217:            l->upReasonValid = 1;
                   1218:        }
                   1219:     } else {
                   1220:        if (l->downReasonValid) {
                   1221:            return;
                   1222:        } else {
                   1223:            l->downReasonValid = 1;
                   1224:        }
                   1225:     }
                   1226: 
                   1227:     /* Allocate buffer if necessary */
                   1228:     if (!*cpp)
                   1229:        *cpp = Malloc(MB_LINK, RBUF_SIZE);
                   1230:     buf = *cpp;
                   1231: 
                   1232:     /* Record reason */
                   1233:     if (fmt) {
                   1234:        snprintf(buf, RBUF_SIZE, "%s:", key);
                   1235:        vsnprintf(buf + strlen(buf), RBUF_SIZE - strlen(buf), fmt, args);
                   1236:     } else 
                   1237:        strlcpy(buf, key, RBUF_SIZE);
                   1238: }
                   1239: 
                   1240: void
                   1241: RecordLinkUpDownReason(Bund b, Link l, int up, const char *key, const char *fmt, ...)
                   1242: {
                   1243:     va_list    args;
                   1244:     int                k;
                   1245: 
                   1246:     if (l != NULL) {
                   1247:        va_start(args, fmt);
                   1248:        RecordLinkUpDownReason2(l, up, key, fmt, args);
                   1249:        va_end(args);
                   1250: 
                   1251:     } else if (b != NULL) {
                   1252:        for (k = 0; k < NG_PPP_MAX_LINKS; k++) {
                   1253:            if (b->links[k]) {
                   1254:                va_start(args, fmt);
                   1255:                RecordLinkUpDownReason2(b->links[k], up, key, fmt, args);
                   1256:                va_end(args);
                   1257:            }
                   1258:        }
                   1259:     }
                   1260: }
                   1261: 
                   1262: const char *
                   1263: LinkMatchAction(Link l, int stage, char *login)
                   1264: {
                   1265:     struct linkaction *a;
                   1266: 
                   1267:     a = SLIST_FIRST(&l->actions);
                   1268:     if (!a) {
                   1269:        Log(LG_LINK, ("[%s] Link: No actions defined", l->name));
                   1270:        return (NULL);
                   1271:     }
                   1272:     if (stage == 1) {
                   1273:        if (SLIST_NEXT(a, next) == NULL && a->regex[0] == 0) {
                   1274:            if (a->action == LINK_ACTION_FORWARD) {
                   1275:                    Log(LG_LINK, ("[%s] Link: Matched action 'forward \"%s\"'",
                   1276:                        l->name, a->arg));
                   1277:                    return (a->arg);
                   1278:            }
                   1279:            if (a->action == LINK_ACTION_DROP) {
                   1280:                    Log(LG_LINK, ("[%s] Link: Matched action 'drop'",
                   1281:                        l->name));
                   1282:                    return ("##DROP##");
                   1283:            }
                   1284:        }
                   1285:        return (NULL);
                   1286:     }
                   1287:     SLIST_FOREACH(a, &l->actions, next) {
                   1288:        if (!a->regex[0] || !regexec(&a->regexp, login, 0, NULL, 0))
                   1289:            break;
                   1290:     }
                   1291:     if (a) {
                   1292:        if (a->action == LINK_ACTION_DROP) {
                   1293:            Log(LG_LINK, ("[%s] Link: Matched action 'drop'",
                   1294:                l->name));
                   1295:            return ("##DROP##");
                   1296:        }
                   1297:        if ((stage == 2 && a->action == LINK_ACTION_FORWARD) ||
                   1298:            (stage == 3 && a->action == LINK_ACTION_BUNDLE)) {
                   1299:            Log(LG_LINK, ("[%s] Link: Matched action '%s \"%s\" \"%s\"'",
                   1300:                l->name, (a->action == LINK_ACTION_FORWARD)?"forward":"bundle",
                   1301:                a->arg, a->regex));
                   1302:            return (a->arg);
                   1303:        }
                   1304:     }
                   1305:     return (NULL);
                   1306: }
                   1307: 
                   1308: /*
                   1309:  * LinkStat()
                   1310:  */
                   1311: 
                   1312: int
1.1.1.4   misho    1313: LinkStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1314: {
                   1315:     Link       l = ctx->lnk;
                   1316:     struct linkaction *a;
                   1317: 
1.1.1.4   misho    1318:     (void)ac;
                   1319:     (void)av;
                   1320:     (void)arg;
                   1321: 
1.1       misho    1322:     Printf("Link %s%s:\r\n", l->name, l->tmpl?" (template)":(l->stay?" (static)":""));
                   1323: 
                   1324:     Printf("Configuration:\r\n");
                   1325:     Printf("\tDevice type    : %s\r\n", l->type?l->type->name:"");
                   1326:     Printf("\tMRU            : %d bytes\r\n", l->conf.mru);
                   1327:     Printf("\tMRRU           : %d bytes\r\n", l->conf.mrru);
                   1328:     Printf("\tCtrl char map  : 0x%08x bytes\r\n", l->conf.accmap);
                   1329:     Printf("\tRetry timeout  : %d seconds\r\n", l->conf.retry_timeout);
                   1330:     Printf("\tMax redial     : ");
                   1331:     if (l->conf.max_redial < 0)
                   1332:        Printf("no redial\r\n");
                   1333:     else if (l->conf.max_redial == 0) 
                   1334:        Printf("unlimited, delay %ds\r\n", l->conf.redial_delay);
                   1335:     else
                   1336:        Printf("%d connect attempts, delay %ds\r\n",
                   1337:            l->conf.max_redial, l->conf.redial_delay);
                   1338:     Printf("\tBandwidth      : %d bits/sec\r\n", l->bandwidth);
                   1339:     Printf("\tLatency        : %d usec\r\n", l->latency);
                   1340:     Printf("\tKeep-alive     : ");
                   1341:     if (l->lcp.fsm.conf.echo_int == 0)
                   1342:        Printf("disabled\r\n");
                   1343:     else
                   1344:        Printf("every %d secs, timeout %d\r\n",
                   1345:            l->lcp.fsm.conf.echo_int, l->lcp.fsm.conf.echo_max);
                   1346:     Printf("\tIdent string   : \"%s\"\r\n", l->conf.ident ? l->conf.ident : "");
                   1347:     if (l->tmpl)
                   1348:        Printf("\tMax children   : %d\r\n", l->conf.max_children);
                   1349:     Printf("Link incoming actions:\r\n");
                   1350:     SLIST_FOREACH(a, &l->actions, next) {
                   1351:        Printf("\t%s\t%s\t%s\r\n", 
                   1352:            (a->action == LINK_ACTION_FORWARD)?"Forward":
                   1353:            (a->action == LINK_ACTION_BUNDLE)?"Bundle":"Drop",
                   1354:            a->arg, a->regex);
                   1355:     }
                   1356:     Printf("Link level options:\r\n");
                   1357:     OptStat(ctx, &l->conf.options, gConfList);
                   1358: 
                   1359:     Printf("Link state:\r\n");
                   1360:     if (l->tmpl)
                   1361:        Printf("\tChildren       : %d\r\n", l->children);
                   1362:     else {
                   1363:        Printf("\tState          : %s\r\n", gPhysStateNames[l->state]);
1.1.1.4.2.1! misho    1364:        Printf("\tAdmin. state   : %s\r\n", linkAdminStateNames[l->admin_state]);
1.1       misho    1365:        Printf("\tSession Id     : %s\r\n", l->session_id);
                   1366:        Printf("\tPeer ident     : %s\r\n", l->lcp.peer_ident);
                   1367:        if (l->state == PHYS_STATE_UP)
                   1368:            Printf("\tSession time   : %ld seconds\r\n", (long int)(time(NULL) - l->last_up));
                   1369:     }
                   1370:     if (!l->tmpl) {
                   1371:        Printf("Up/Down stats:\r\n");
                   1372:        if (l->downReason && (!l->downReasonValid))
                   1373:            Printf("\tDown Reason    : %s\r\n", l->downReason);
                   1374:        if (l->upReason)
                   1375:            Printf("\tUp Reason      : %s\r\n", l->upReason);
                   1376:        if (l->downReason && l->downReasonValid)
                   1377:            Printf("\tDown Reason    : %s\r\n", l->downReason);
                   1378:   
                   1379:        if (l->bund) {
                   1380:            LinkUpdateStats(l);
                   1381:            Printf("Traffic stats:\r\n");
                   1382: 
                   1383:            Printf("\tInput octets   : %llu\r\n", (unsigned long long)l->stats.recvOctets);
                   1384:            Printf("\tInput frames   : %llu\r\n", (unsigned long long)l->stats.recvFrames);
                   1385:            Printf("\tOutput octets  : %llu\r\n", (unsigned long long)l->stats.xmitOctets);
                   1386:            Printf("\tOutput frames  : %llu\r\n", (unsigned long long)l->stats.xmitFrames);
                   1387:            Printf("\tBad protocols  : %llu\r\n", (unsigned long long)l->stats.badProtos);
                   1388:            Printf("\tRunts          : %llu\r\n", (unsigned long long)l->stats.runts);
                   1389:            Printf("\tDup fragments  : %llu\r\n", (unsigned long long)l->stats.dupFragments);
                   1390:            Printf("\tDrop fragments : %llu\r\n", (unsigned long long)l->stats.dropFragments);
                   1391:        }
                   1392:     }
                   1393:     return(0);
                   1394: }
                   1395: 
                   1396: /* 
                   1397:  * LinkUpdateStats()
                   1398:  */
                   1399: 
                   1400: void
                   1401: LinkUpdateStats(Link l)
                   1402: {
                   1403: #ifndef NG_PPP_STATS64
                   1404:     struct ng_ppp_link_stat    stats;
                   1405: 
                   1406:     if (NgFuncGetStats(l->bund, l->bundleIndex, &stats) != -1) {
                   1407:        l->stats.xmitFrames += abs(stats.xmitFrames - l->oldStats.xmitFrames);
                   1408:        l->stats.xmitOctets += abs(stats.xmitOctets - l->oldStats.xmitOctets);
                   1409:        l->stats.recvFrames += abs(stats.recvFrames - l->oldStats.recvFrames);
                   1410:        l->stats.recvOctets += abs(stats.recvOctets - l->oldStats.recvOctets);
                   1411:         l->stats.badProtos  += abs(stats.badProtos - l->oldStats.badProtos);
                   1412:         l->stats.runts   += abs(stats.runts - l->oldStats.runts);
                   1413:         l->stats.dupFragments += abs(stats.dupFragments - l->oldStats.dupFragments);
                   1414:         l->stats.dropFragments += abs(stats.dropFragments - l->oldStats.dropFragments);
1.1.1.3   misho    1415:        l->oldStats = stats;
1.1       misho    1416:     }
                   1417: 
                   1418: #else
                   1419:     NgFuncGetStats64(l->bund, l->bundleIndex, &l->stats);
                   1420: #endif
                   1421: }
                   1422: 
                   1423: /*
                   1424:  * LinkResetStats()
                   1425:  */
                   1426: 
                   1427: void
                   1428: LinkResetStats(Link l)
                   1429: {
                   1430:     if (l->bund)
                   1431:        NgFuncClrStats(l->bund, l->bundleIndex);
                   1432:     memset(&l->stats, 0, sizeof(l->stats));
                   1433: #ifndef NG_PPP_STATS64
                   1434:     memset(&l->oldStats, 0, sizeof(l->oldStats));
                   1435: #endif
                   1436: }
                   1437: 
                   1438: /*
                   1439:  * LinkSetCommand()
                   1440:  */
                   1441: 
                   1442: static int
1.1.1.4   misho    1443: LinkSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1444: {
                   1445:     Link       l = ctx->lnk;
                   1446:     int                val, nac = 0;
                   1447:     const char *name;
1.1.1.4   misho    1448:     const char *nav[ac];
1.1       misho    1449:     const char *av2[] = { "chap-md5", "chap-msv1", "chap-msv2" };
                   1450: 
                   1451:     /* make "chap" as an alias for all chap-variants, this should keep BC */
                   1452:     switch ((intptr_t)arg) {
                   1453:        case SET_ACCEPT:
                   1454:         case SET_DENY:
                   1455:         case SET_ENABLE:
                   1456:         case SET_DISABLE:
                   1457:         case SET_YES:
                   1458:         case SET_NO:
                   1459:         {
                   1460:            int i = 0;
                   1461:             for ( ; i < ac; i++) {
                   1462:                if (strcasecmp(av[i], "chap") == 0) {
1.1.1.4   misho    1463:                    LinkSetCommand(ctx, 3, (const char **)av2, arg);
1.1       misho    1464:                } else {
                   1465:                    nav[nac++] = av[i];
                   1466:                } 
                   1467:            }
                   1468:            av = nav;
                   1469:            ac = nac;
                   1470:            break;
                   1471:        }
                   1472:     }
                   1473: 
                   1474:     switch ((intptr_t)arg) {
                   1475:        case SET_BANDWIDTH:
                   1476:            if (ac != 1)
                   1477:                return(-1);
                   1478: 
                   1479:            val = atoi(*av);
                   1480:            if (val <= 0)
                   1481:                Error("[%s] Bandwidth must be positive", l->name);
                   1482:            else if (val > NG_PPP_MAX_BANDWIDTH * 10 * 8) {
                   1483:                l->bandwidth = NG_PPP_MAX_BANDWIDTH * 10 * 8;
                   1484:                Log(LG_ERR, ("[%s] Bandwidth truncated to %d bit/s", l->name, 
                   1485:                    l->bandwidth));
                   1486:            } else
                   1487:                l->bandwidth = val;
                   1488:            break;
                   1489: 
                   1490:        case SET_LATENCY:
                   1491:            if (ac != 1)
                   1492:                return(-1);
                   1493: 
                   1494:            val = atoi(*av);
                   1495:            if (val < 0)
                   1496:                Error("[%s] Latency must be not negative", l->name);
                   1497:            else if (val > NG_PPP_MAX_LATENCY * 1000) {
                   1498:                Log(LG_ERR, ("[%s] Latency truncated to %d usec", l->name, 
                   1499:                    NG_PPP_MAX_LATENCY * 1000));
                   1500:                l->latency = NG_PPP_MAX_LATENCY * 1000;
                   1501:            } else
                   1502:                l->latency = val;
                   1503:            break;
                   1504: 
                   1505:        case SET_BUNDLE:
                   1506:        case SET_FORWARD:
                   1507:        case SET_DROP:
                   1508:            {
                   1509:                struct linkaction       *n, *a;
                   1510:            
                   1511:                if ((ac < 1 && (intptr_t)arg != SET_DROP) || ac > 2)
                   1512:                    return(-1);
                   1513: 
                   1514:                n = Malloc(MB_LINK, sizeof(struct linkaction));
                   1515:                if ((intptr_t)arg != SET_DROP) {
                   1516:                    n->action = ((intptr_t)arg == SET_BUNDLE)?
                   1517:                        LINK_ACTION_BUNDLE:LINK_ACTION_FORWARD;
                   1518:                    strlcpy(n->arg, av[0], sizeof(n->arg));
                   1519:                    if (ac == 2 && av[1][0]) {
                   1520:                        strlcpy(n->regex, av[1], sizeof(n->regex));
                   1521:                        if (regcomp(&n->regexp, n->regex, REG_EXTENDED)) {
                   1522:                            Freee(n);
                   1523:                            Error("regexp \"%s\" compilation error", av[1]);
                   1524:                        }
                   1525:                    }
                   1526:                } else {
                   1527:                    n->action = LINK_ACTION_DROP;
                   1528:                    if (ac == 1 && av[0][0]) {
                   1529:                        strlcpy(n->regex, av[0], sizeof(n->regex));
                   1530:                        if (regcomp(&n->regexp, n->regex, REG_EXTENDED)) {
                   1531:                            Freee(n);
                   1532:                            Error("regexp \"%s\" compilation error", av[0]);
                   1533:                        }
                   1534:                    }
                   1535:                }
                   1536:            
                   1537:                a = SLIST_FIRST(&ctx->lnk->actions);
                   1538:                if (a) {
                   1539:                    while (SLIST_NEXT(a, next))
                   1540:                        a = SLIST_NEXT(a, next);
                   1541:                    SLIST_INSERT_AFTER(a, n, next);
                   1542:                } else {
                   1543:                    SLIST_INSERT_HEAD(&ctx->lnk->actions, n, next);
                   1544:                }
                   1545:            }
                   1546:            break;
                   1547: 
                   1548:        case SET_CLEAR:
                   1549:            {
                   1550:                struct linkaction       *a;
                   1551:            
                   1552:                if (ac != 0)
                   1553:                    return(-1);
                   1554: 
                   1555:                while ((a = SLIST_FIRST(&l->actions)) != NULL) {
                   1556:                    SLIST_REMOVE_HEAD(&l->actions, next);
                   1557:                    if (a->regex[0])
                   1558:                        regfree(&a->regexp);
                   1559:                    Freee(a);
                   1560:                }
                   1561:            }
                   1562:            break;
                   1563: 
                   1564:        case SET_MRU:
                   1565:        case SET_MTU:
                   1566:            if (ac != 1)
                   1567:                return(-1);
                   1568: 
                   1569:            val = atoi(*av);
                   1570:            name = ((intptr_t)arg == SET_MTU) ? "MTU" : "MRU";
                   1571:            if (val < LCP_MIN_MRU)
                   1572:                Error("min %s is %d", name, LCP_MIN_MRU);
1.1.1.4.2.1! misho    1573:            else if (l->type && (val > l->type->mtu)) {
1.1       misho    1574:                Error("max %s on type \"%s\" links is %d",
1.1.1.4.2.1! misho    1575:                    name, l->type->name, l->type->mtu);
1.1       misho    1576:            } else if ((intptr_t)arg == SET_MTU)
                   1577:                l->conf.mtu = val;
                   1578:            else
                   1579:                l->conf.mru = val;
                   1580:            break;
                   1581: 
                   1582:        case SET_MRRU:
                   1583:            if (ac != 1)
                   1584:                return(-1);
                   1585: 
                   1586:            val = atoi(*av);
                   1587:            if (val < MP_MIN_MRRU)
                   1588:                Error("min MRRU is %d", MP_MIN_MRRU);
                   1589:            else if (val > MP_MAX_MRRU)
                   1590:                Error("max MRRU is %d", MP_MAX_MRRU);
                   1591:            else
                   1592:                l->conf.mrru = val;
                   1593:            break;
                   1594: 
                   1595:        case SET_FSM_RETRY:
                   1596:            if (ac != 1)
                   1597:                return(-1);
                   1598: 
                   1599:            val = atoi(*av);
                   1600:            if (val < 1 || val > 10) {
                   1601:                Error("incorrect fsm-timeout value %d", val);
                   1602:            } else {
                   1603:                l->conf.retry_timeout = val;
                   1604:            }
                   1605:            break;
                   1606: 
                   1607:        case SET_MAX_RETRY:
                   1608:            if (ac != 1)
                   1609:                return(-1);
                   1610: 
                   1611:            l->conf.max_redial = atoi(*av);
                   1612:            break;
                   1613: 
                   1614:        case SET_RETRY_DELAY:
                   1615:            if (ac != 1)
                   1616:                return(-1);
                   1617: 
                   1618:            l->conf.redial_delay = atoi(*av);
                   1619:            if (l->conf.redial_delay < 1)
                   1620:                l->conf.redial_delay = 1;
                   1621:            break;
                   1622: 
                   1623:        case SET_MAX_CHILDREN:
                   1624:            if (ac != 1)
                   1625:                return(-1);
                   1626: 
                   1627:            if (!l->tmpl)
                   1628:                Error("applicable only to templates");
                   1629:            val = atoi(*av);
                   1630:            if (val < 0 || val > 100000)
                   1631:                Error("incorrect value %d", val);
                   1632:            l->conf.max_children = val;
                   1633:            break;
                   1634: 
                   1635:        case SET_ACCMAP:
                   1636:            if (ac != 1)
                   1637:                return(-1);
                   1638: 
                   1639:            sscanf(*av, "%x", &val);
                   1640:            l->conf.accmap = val;
                   1641:            break;
                   1642: 
                   1643:        case SET_KEEPALIVE:
                   1644:            if (ac != 2)
                   1645:                return(-1);
                   1646:            l->lcp.fsm.conf.echo_int = atoi(av[0]);
                   1647:            l->lcp.fsm.conf.echo_max = atoi(av[1]);
                   1648:            break;
                   1649: 
                   1650:        case SET_IDENT:
                   1651:            if (ac != 1)
                   1652:                return(-1);
                   1653:            if (l->conf.ident != NULL) {
                   1654:                Freee(l->conf.ident);
                   1655:                l->conf.ident = NULL;
                   1656:            }
                   1657:            if (*av[0] != '\0')
                   1658:            strcpy(l->conf.ident = Malloc(MB_LINK, strlen(av[0]) + 1), av[0]);
                   1659:            break;
                   1660: 
                   1661:        case SET_ACCEPT:
                   1662:            AcceptCommand(ac, av, &l->conf.options, gConfList);
                   1663:            if (ctx->lnk->type->update)
                   1664:                (ctx->lnk->type->update)(ctx->lnk);
                   1665:            break;
                   1666: 
                   1667:        case SET_DENY:
                   1668:            DenyCommand(ac, av, &l->conf.options, gConfList);
                   1669:            if (ctx->lnk->type->update)
                   1670:                (ctx->lnk->type->update)(ctx->lnk);
                   1671:            break;
                   1672: 
                   1673:        case SET_ENABLE:
                   1674:            EnableCommand(ac, av, &l->conf.options, gConfList);
                   1675:            if (ctx->lnk->type->update)
                   1676:                (ctx->lnk->type->update)(ctx->lnk);
                   1677:            break;
                   1678: 
                   1679:        case SET_DISABLE:
                   1680:            DisableCommand(ac, av, &l->conf.options, gConfList);
                   1681:            if (ctx->lnk->type->update)
                   1682:                (ctx->lnk->type->update)(ctx->lnk);
                   1683:            break;
                   1684: 
                   1685:        case SET_YES:
                   1686:            YesCommand(ac, av, &l->conf.options, gConfList);
                   1687:            if (ctx->lnk->type->update)
                   1688:                (ctx->lnk->type->update)(ctx->lnk);
                   1689:            break;
                   1690: 
                   1691:        case SET_NO:
                   1692:            NoCommand(ac, av, &l->conf.options, gConfList);
                   1693:            if (ctx->lnk->type->update)
                   1694:                (ctx->lnk->type->update)(ctx->lnk);
                   1695:            break;
                   1696: 
                   1697:        default:
                   1698:            assert(0);
                   1699:     }
                   1700: 
                   1701:     return(0);
                   1702: }
                   1703: 

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