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