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

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

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