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, <->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>