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