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