Annotation of embedaddon/mpd/src/fsm.c, revision 1.1.1.3
1.1 misho 1:
2: /*
3: * fsm.c
4: *
5: * Written by Toshiharu OHNO <tony-o@iij.ad.jp>
6: * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved.
7: * See ``COPYRIGHT.iij''
8: *
9: * Rewritten by Archie Cobbs <archie@freebsd.org>
10: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
11: * See ``COPYRIGHT.whistle''
12: */
13:
14: #include "ppp.h"
15: #include "fsm.h"
16: #include "ngfunc.h"
17: #include "util.h"
18:
19: /*
20: * DEFINITIONS
21: */
22:
23: #define FSM_MAXCONFIG 10
24: #define FSM_MAXNAK 10
25: #define FSM_MAX_OPTS 100
26: #define FSM_MAXTERMINATE 2
27: #define FSM_MAXFAILURE 5
28:
29: /* FSM restart options */
30:
31: /* #define RESTART_OPENED */
32: /* #define RESTART_CLOSING */
33: /* #define RESTART_STOPPED */
34:
35: struct fsmcodedesc {
36: void (*action)(Fsm fp, FsmHeader hdr, Mbuf bp);
37: const char *name;
38: };
39:
40: /* Size of REQ, ACK, NAK, and REJ buffers */
41:
42: #define REQ_BUFFER_SIZE 256
43: #define REJ_BUFFER_SIZE 256
44: #define ACK_BUFFER_SIZE 256
45: #define NAK_BUFFER_SIZE 256
46:
47: /*
48: * INTERNAL FUNCTIONS
49: */
50:
51: static void FsmNewState(Fsm f, enum fsm_state state);
52:
53: static void FsmSendConfigReq(Fsm fp);
54: static void FsmSendTerminateReq(Fsm fp);
55: static void FsmSendTerminateAck(Fsm fp);
56: static void FsmInitRestartCounter(Fsm fp, int value);
57: static void FsmInitMaxFailure(Fsm fp, int value);
58: static void FsmInitMaxConfig(Fsm fp, int value);
59: static void FsmTimeout(void *arg);
60:
61: static void FsmRecvConfigReq(Fsm fp, FsmHeader lhp, Mbuf bp);
62: static void FsmRecvConfigAck(Fsm fp, FsmHeader lhp, Mbuf bp);
63: static void FsmRecvConfigNak(Fsm fp, FsmHeader lhp, Mbuf bp);
64: static void FsmRecvTermReq(Fsm fp, FsmHeader lhp, Mbuf bp);
65: static void FsmRecvTermAck(Fsm fp, FsmHeader lhp, Mbuf bp);
66: static void FsmRecvConfigRej(Fsm fp, FsmHeader lhp, Mbuf bp);
67: static void FsmRecvCodeRej(Fsm fp, FsmHeader lhp, Mbuf bp);
68: static void FsmRecvProtoRej(Fsm fp, FsmHeader lhp, Mbuf bp);
69: static void FsmRecvEchoReq(Fsm fp, FsmHeader lhp, Mbuf bp);
70: static void FsmRecvEchoRep(Fsm fp, FsmHeader lhp, Mbuf bp);
71: static void FsmRecvDiscReq(Fsm fp, FsmHeader lhp, Mbuf bp);
72: static void FsmRecvIdent(Fsm fp, FsmHeader lhp, Mbuf bp);
73: static void FsmRecvTimeRemain(Fsm fp, FsmHeader lhp, Mbuf bp);
74: static void FsmRecvResetReq(Fsm fp, FsmHeader lhp, Mbuf bp);
75: static void FsmRecvResetAck(Fsm fp, FsmHeader lhp, Mbuf bp);
76: static void FsmRecvVendor(Fsm fp, FsmHeader lhp, Mbuf bp);
77: static void FsmRecvRxjPlus(Fsm fp);
78:
79: static void FsmLayerUp(Fsm fp);
80: static void FsmLayerDown(Fsm fp);
81: static void FsmLayerStart(Fsm fp);
82: static void FsmLayerFinish(Fsm fp);
83:
84: static Mbuf FsmCheckMagic(Fsm fp, Mbuf bp);
85: static void FsmEchoTimeout(void *arg);
86: static void FsmDecodeBuffer(Fsm fp, u_char *buf, int size, int mode);
87: static int FsmExtractOptions(Fsm fp, u_char *data,
88: int dlen, FsmOption opts, int max);
89:
90: /*
91: * GLOBAL VARIABLES
92: */
93:
94: u_int gAckSize, gNakSize, gRejSize;
95:
96: /*
97: * INTERNAL VARIABLES
98: */
99:
100: /*
101: * It's OK for these to be statically allocated, because we always
102: * do our work with them all in one whole step without stopping.
103: */
104:
105: static u_char gRejBuf[REJ_BUFFER_SIZE];
106: static u_char gAckBuf[ACK_BUFFER_SIZE];
107: static u_char gNakBuf[NAK_BUFFER_SIZE];
108:
109: static const struct fsmcodedesc FsmCodes[] = {
110: { FsmRecvVendor, "Vendor Packet" },
111: { FsmRecvConfigReq, "Configure Request" },
112: { FsmRecvConfigAck, "Configure Ack" },
113: { FsmRecvConfigNak, "Configure Nak" },
114: { FsmRecvConfigRej, "Configure Reject" },
115: { FsmRecvTermReq, "Terminate Request" },
116: { FsmRecvTermAck, "Terminate Ack" },
117: { FsmRecvCodeRej, "Code Reject" },
118: { FsmRecvProtoRej, "Protocol Reject" },
119: { FsmRecvEchoReq, "Echo Request" },
120: { FsmRecvEchoRep, "Echo Reply" },
121: { FsmRecvDiscReq, "Discard Request" },
122: { FsmRecvIdent, "Ident" },
123: { FsmRecvTimeRemain, "Time Remain" },
124: { FsmRecvResetReq, "Reset Request" },
125: { FsmRecvResetAck, "Reset Ack" },
126: };
127:
128: #define NUM_FSM_CODES (sizeof(FsmCodes) / sizeof(*FsmCodes))
129:
130: /*
131: * FsmInit()
132: *
133: * Initialize FSM structure and install some default values
134: */
135:
136: void
137: FsmInit(Fsm fp, FsmType type, void *arg)
138: {
139: memset(fp, 0, sizeof(*fp));
140: fp->type = type;
141: fp->arg = arg;
142: fp->log = LG_FSM | type->log;
143: fp->log2 = LG_FSM | type->log2;
144: fp->conf.maxconfig = FSM_MAXCONFIG;
145: fp->conf.maxterminate = FSM_MAXTERMINATE;
146: fp->conf.maxfailure = FSM_MAXFAILURE;
147: fp->conf.check_magic = FALSE;
148: fp->conf.passive = FALSE;
149: fp->state = ST_INITIAL;
150: fp->reqid = 1;
151: fp->rejid = 1;
152: fp->echoid = 1;
153: }
154:
155: /*
156: * FsmInst()
157: *
158: * Instantiate FSM structure from template
159: */
160:
161: void
162: FsmInst(Fsm fp, Fsm fpt, void *arg)
163: {
164: memcpy(fp, fpt, sizeof(*fp));
165: fp->arg = arg;
166: }
167:
168: /*
169: * FsmNewState()
170: *
171: * Change state of a FSM. Also, call the configuration routine
172: * if this is an appropriate time.
173: */
174:
175: void
176: FsmNewState(Fsm fp, enum fsm_state new)
177: {
178: enum fsm_state old;
179:
180: /* Log it */
181: Log(fp->log2, ("[%s] %s: state change %s --> %s",
182: Pref(fp), Fsm(fp), FsmStateName(fp->state), FsmStateName(new)));
183:
184: /* Change state and call protocol's own handler, if any */
185: old = fp->state;
186: if (fp->type->NewState)
187: (*fp->type->NewState)(fp, old, new);
188: fp->state = new;
189: if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED))
190: TimerStop(&fp->timer);
191:
192: /* Turn on/off keep-alive echo packets (if so configured) */
193: if (old == ST_OPENED)
194: TimerStop(&fp->echoTimer);
195: if (new == ST_OPENED && fp->conf.echo_int != 0) {
196: fp->quietCount = 0;
197: memset(&fp->idleStats, 0, sizeof(fp->idleStats));
198: TimerInit(&fp->echoTimer, "FsmKeepAlive",
199: fp->conf.echo_int * SECONDS, FsmEchoTimeout, fp);
200: TimerStartRecurring(&fp->echoTimer);
201: }
202: }
203:
204: /*
205: * FsmOutputMbuf()
206: *
207: * Send out a control packet with specified contents. Consumes the mbuf.
208: */
209:
210: void
211: FsmOutputMbuf(Fsm fp, u_int code, u_int id, Mbuf payload)
212: {
213: Bund b;
214: Mbuf bp;
215: struct fsmheader hdr;
216:
217: if (fp->type->link_layer)
218: b = ((Link)fp->arg)->bund;
219: else
220: b = (Bund)fp->arg;
221:
222: /* Build header */
223: hdr.id = id;
224: hdr.code = code;
225: hdr.length = htons(sizeof(hdr) + MBLEN(payload));
226:
227: /* Prepend to payload */
228: bp = mbcopyback(payload, -(int)sizeof(hdr), &hdr, sizeof(hdr));
229:
230: /* Send it out */
231: if (fp->type->link_layer) {
232: NgFuncWritePppFrameLink((Link)fp->arg, fp->type->proto, bp);
233: } else {
234: NgFuncWritePppFrame(b, NG_PPP_BUNDLE_LINKNUM, fp->type->proto, bp);
235: }
236: }
237:
238: /*
239: * FsmOutput()
240: *
241: * Send out a control packet with specified contents
242: */
243:
244: void
245: FsmOutput(Fsm fp, u_int code, u_int id, u_char *ptr, int len)
246: {
247: Mbuf bp;
248:
249: bp = (len > 0) ? mbcopyback(NULL, 0, ptr, len) : NULL;
250: FsmOutputMbuf(fp, code, id, bp);
251: }
252:
253: /*
254: * FsmOpen()
255: *
256: * XXX The use of the restart option should probably be
257: * XXX configured per FSM via the initialization structure.
258: * XXX For now, we just make it mandatory via #ifdef's.
259: */
260:
261: void
262: FsmOpen(Fsm fp)
263: {
264: Log(fp->log2, ("[%s] %s: Open event", Pref(fp), Fsm(fp)));
265: switch (fp->state) {
266: case ST_INITIAL:
267: FsmNewState(fp, ST_STARTING);
268: FsmLayerStart(fp);
269: break;
270: case ST_STARTING:
271: break;
272: case ST_CLOSED:
273: if (fp->type->Configure)
274: (*fp->type->Configure)(fp);
275: FsmNewState(fp, ST_REQSENT);
276: FsmLayerStart(fp); /* Missing in RFC 1661 */
277: FsmInitRestartCounter(fp, fp->conf.maxconfig);
278: FsmInitMaxFailure(fp, fp->conf.maxfailure);
279: FsmInitMaxConfig(fp, fp->conf.maxconfig);
280: FsmSendConfigReq(fp);
281: break;
282: case ST_REQSENT:
283: case ST_ACKRCVD:
284: case ST_ACKSENT:
285: break;
286:
287: case ST_OPENED:
288: #ifdef RESTART_OPENED
289: FsmDown(fp);
290: FsmUp(fp);
291: #endif
292: break;
293:
294: case ST_CLOSING:
295: FsmNewState(fp, ST_STOPPING);
296: case ST_STOPPING:
297: #ifdef RESTART_CLOSING
298: FsmDown(fp);
299: FsmUp(fp);
300: #endif
301: break;
302:
303: case ST_STOPPED:
304: #ifdef RESTART_STOPPED
305: FsmDown(fp);
306: FsmUp(fp);
307: #endif
308: break;
309: }
310: }
311:
312: void
313: FsmUp(Fsm fp)
314: {
315: Log(fp->log2, ("[%s] %s: Up event", Pref(fp), Fsm(fp)));
316: switch (fp->state) {
317: case ST_INITIAL:
318: FsmNewState(fp, ST_CLOSED);
319: break;
320: case ST_STARTING:
321: if (fp->type->Configure)
322: (*fp->type->Configure)(fp);
323: FsmNewState(fp, ST_REQSENT);
324: FsmInitRestartCounter(fp, fp->conf.maxconfig);
325: FsmInitMaxFailure(fp, fp->conf.maxfailure);
326: FsmInitMaxConfig(fp, fp->conf.maxconfig);
327: FsmSendConfigReq(fp);
328: break;
329: default:
330: Log(fp->log2, ("[%s] %s: Oops, UP at %s",
331: Pref(fp), Fsm(fp), FsmStateName(fp->state)));
332: break;
333: }
334: }
335:
336: void
337: FsmDown(Fsm fp)
338: {
339: Log(fp->log2, ("[%s] %s: Down event", Pref(fp), Fsm(fp)));
340: switch (fp->state) {
341: case ST_CLOSING:
342: FsmLayerFinish(fp); /* Missing in RFC 1661 */
343: /* fall through */
344: case ST_CLOSED:
345: FsmNewState(fp, ST_INITIAL);
346: break;
347: case ST_STOPPED:
348: FsmNewState(fp, ST_STARTING);
349: FsmLayerStart(fp);
350: break;
351: case ST_STOPPING:
352: case ST_REQSENT:
353: case ST_ACKRCVD:
354: case ST_ACKSENT:
355: FsmNewState(fp, ST_STARTING);
356: if (fp->type->UnConfigure)
357: (*fp->type->UnConfigure)(fp);
358: break;
359: case ST_OPENED:
360: FsmNewState(fp, ST_STARTING);
361: FsmLayerDown(fp);
362: if (fp->type->UnConfigure)
363: (*fp->type->UnConfigure)(fp);
364: break;
365: default:
366: break;
367: }
368: }
369:
370: void
371: FsmClose(Fsm fp)
372: {
373: Log(fp->log2, ("[%s] %s: Close event", Pref(fp), Fsm(fp)));
374: switch (fp->state) {
375: case ST_STARTING:
376: FsmNewState(fp, ST_INITIAL);
377: FsmLayerFinish(fp);
378: break;
379: case ST_STOPPED:
380: FsmNewState(fp, ST_CLOSED);
381: break;
382: case ST_STOPPING:
383: FsmNewState(fp, ST_CLOSING);
384: break;
385: case ST_OPENED:
386: FsmNewState(fp, ST_CLOSING);
387: FsmInitRestartCounter(fp, fp->conf.maxterminate);
388: FsmSendTerminateReq(fp);
389: FsmLayerDown(fp);
390: if (fp->type->UnConfigure)
391: (*fp->type->UnConfigure)(fp);
392: break;
393: case ST_REQSENT:
394: case ST_ACKRCVD:
395: case ST_ACKSENT:
396: FsmNewState(fp, ST_CLOSING);
397: FsmInitRestartCounter(fp, fp->conf.maxterminate);
398: FsmSendTerminateReq(fp);
399: if (fp->type->UnConfigure)
400: (*fp->type->UnConfigure)(fp);
401: break;
402: default:
403: break;
404: }
405: }
406:
407: /*
408: * Send functions
409: */
410:
411: static void
412: FsmSendConfigReq(Fsm fp)
413: {
414: u_char reqBuf[REQ_BUFFER_SIZE];
415: u_char *cp;
416:
417: /* Build and display config request */
418: Log(fp->log, ("[%s] %s: SendConfigReq #%d", Pref(fp), Fsm(fp), fp->reqid));
419: cp = (*fp->type->BuildConfigReq)(fp, reqBuf);
420: FsmDecodeBuffer(fp, reqBuf, cp - reqBuf, MODE_NOP);
421:
422: /* Send it */
423: FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, reqBuf, cp - reqBuf);
424:
425: /* Restart restart timer and decrement restart counter */
426: TimerStart(&fp->timer);
427: fp->restart--;
428: fp->config--;
429: }
430:
431: static void
432: FsmSendTerminateReq(Fsm fp)
433: {
434: Log(fp->log, ("[%s] %s: SendTerminateReq #%d", Pref(fp), Fsm(fp), fp->reqid));
435: FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
436: if (fp->type->SendTerminateReq)
437: (*fp->type->SendTerminateReq)(fp);
438: TimerStart(&fp->timer); /* Restart restart timer */
439: fp->restart--; /* Decrement restart counter */
440: }
441:
442: static void
443: FsmSendTerminateAck(Fsm fp)
444: {
445: Log(fp->log, ("[%s] %s: SendTerminateAck #%d", Pref(fp), Fsm(fp), fp->reqid));
446: FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
447: if (fp->type->SendTerminateAck)
448: (*fp->type->SendTerminateAck)(fp);
449: }
450:
451: static void
452: FsmSendConfigAck(Fsm fp, FsmHeader lhp, u_char *option, int count)
453: {
454: Log(fp->log, ("[%s] %s: SendConfigAck #%d", Pref(fp), Fsm(fp), lhp->id));
455: FsmDecodeBuffer(fp, option, count, MODE_NOP);
456: FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
457: }
458:
459: static void
460: FsmSendConfigRej(Fsm fp, FsmHeader lhp, u_char *option, int count)
461: {
462: Log(fp->log, ("[%s] %s: SendConfigRej #%d", Pref(fp), Fsm(fp), lhp->id));
463: FsmDecodeBuffer(fp, option, count, MODE_NOP);
464: FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
465: fp->failure--;
466: }
467:
468: static void
469: FsmSendConfigNak(Fsm fp, FsmHeader lhp, u_char *option, int count)
470: {
471: Log(fp->log, ("[%s] %s: SendConfigNak #%d", Pref(fp), Fsm(fp), lhp->id));
472: FsmDecodeBuffer(fp, option, count, MODE_NOP);
473: FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
474: fp->failure--;
475: }
476:
477: /*
478: * Timeout actions
479: */
480:
481: static void
482: FsmTimeout(void *arg)
483: {
484: Fsm fp = (Fsm) arg;
485:
486: if (fp->restart > 0) { /* TO+ */
487: switch (fp->state) {
488: case ST_CLOSING:
489: case ST_STOPPING:
490: FsmSendTerminateReq(fp);
491: break;
492: case ST_REQSENT:
493: case ST_ACKSENT:
494: FsmSendConfigReq(fp);
495: break;
496: case ST_ACKRCVD:
497: FsmNewState(fp, ST_REQSENT);
498: FsmSendConfigReq(fp);
499: break;
500: default:
501: break;
502: }
503: } else { /* TO- */
504: switch (fp->state) {
505: case ST_CLOSING:
506: FsmNewState(fp, ST_CLOSED);
507: FsmLayerFinish(fp);
508: break;
509: case ST_STOPPING:
510: FsmNewState(fp, ST_STOPPED);
511: FsmLayerFinish(fp);
512: break;
513: case ST_REQSENT:
514: case ST_ACKSENT:
515: case ST_ACKRCVD:
516: FsmFailure(fp, FAIL_NEGOT_FAILURE);
517: break;
518: default:
519: break;
520: }
521: }
522: }
523:
524: void
525: FsmInitRestartCounter(Fsm fp, int value)
526: {
527: const int retry = fp->type->link_layer ?
528: ((Link)(fp->arg))->conf.retry_timeout :
529: ((Bund)(fp->arg))->conf.retry_timeout;
530:
531: TimerStop(&fp->timer);
532: TimerInit(&fp->timer,
533: fp->type->name, retry * SECONDS, FsmTimeout, (void *) fp);
534: fp->restart = value;
535: }
536:
537: void
538: FsmInitMaxFailure(Fsm fp, int value)
539: {
540: fp->failure = value;
541: }
542:
543: void
544: FsmInitMaxConfig(Fsm fp, int value)
545: {
546: fp->config = value;
547: }
548:
549: /*
550: * Actions that happen when we receive packets
551: */
552:
553: /* RCR */
554:
555: static void
556: FsmRecvConfigReq(Fsm fp, FsmHeader lhp, Mbuf bp)
557: {
558: int fullyAcked;
559:
560: /* Check and process easy cases */
561: switch (fp->state) {
562: case ST_INITIAL:
563: case ST_STARTING:
564: Log(fp->log2, ("[%s] %s: Oops, RCR in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
565: mbfree(bp);
566: return;
567: case ST_CLOSED:
568: FsmSendTerminateAck(fp);
569: mbfree(bp);
570: return;
571: case ST_STOPPED:
572: if (fp->type->Configure)
573: (*fp->type->Configure)(fp);
574: break;
575: case ST_CLOSING:
576: case ST_STOPPING:
577: mbfree(bp);
578: return;
579: default:
580: break;
581: }
582:
583: /* Decode packet */
584: FsmDecodeBuffer(fp, MBDATA(bp), MBLEN(bp), MODE_REQ);
585:
586: /* State specific actions */
587: switch (fp->state) {
588: case ST_OPENED:
589: FsmLayerDown(fp);
590: FsmSendConfigReq(fp);
591: break;
592: case ST_STOPPED:
593: FsmLayerStart(fp); /* Missing in RFC 1661 */
594: FsmInitRestartCounter(fp, fp->conf.maxconfig);
595: FsmInitMaxFailure(fp, fp->conf.maxfailure);
596: FsmInitMaxConfig(fp, fp->conf.maxconfig);
597: FsmSendConfigReq(fp);
598: break;
599: default:
600: break;
601: }
602:
603: /* What did we think of packet? */
604: fullyAcked = (gNakSize == 0 && gRejSize == 0);
605: if (fullyAcked)
606: FsmSendConfigAck(fp, lhp, gAckBuf, gAckSize);
607: else {
608: if (fp->failure <= 0) {
609: Log(fp->log, ("[%s] %s: not converging", Pref(fp), Fsm(fp)));
610: FsmFailure(fp, FAIL_NEGOT_FAILURE);
611: mbfree(bp);
612: return;
613: } else {
614: if (gRejSize)
615: FsmSendConfigRej(fp, lhp, gRejBuf, gRejSize);
616: else if (gNakSize)
617: FsmSendConfigNak(fp, lhp, gNakBuf, gNakSize);
618: }
619: }
620:
621: /* Continue with state transition */
622: switch (fp->state) {
623: case ST_STOPPED:
624: case ST_OPENED:
625: if (fullyAcked)
626: FsmNewState(fp, ST_ACKSENT);
627: else
628: FsmNewState(fp, ST_REQSENT);
629: break;
630: case ST_REQSENT:
631: if (fullyAcked)
632: FsmNewState(fp, ST_ACKSENT);
633: break;
634: case ST_ACKRCVD:
635: if (fullyAcked)
636: {
637: FsmNewState(fp, ST_OPENED);
638: FsmLayerUp(fp);
639: }
640: break;
641: case ST_ACKSENT:
642: if (!fullyAcked)
643: FsmNewState(fp, ST_REQSENT);
644: break;
645: default:
646: break;
647: }
648: mbfree(bp);
649: }
650:
651: /* RCA */
652:
653: static void
654: FsmRecvConfigAck(Fsm fp, FsmHeader lhp, Mbuf bp)
655: {
656:
657: /* Check sequence number */
658: if (lhp->id != (u_char) (fp->reqid - 1)) {
659: Log(fp->log, ("[%s] Wrong id#, expecting %d", Pref(fp), (u_char) (fp->reqid - 1)));
660: mbfree(bp);
661: return;
662: }
663:
664: /* XXX We should verify the contents are equal to our last sent config-req */
665:
666: /* Decode packet */
667: FsmDecodeBuffer(fp, MBDATA(bp), MBLEN(bp), MODE_NOP);
668:
669: /* Do whatever */
670: switch (fp->state) {
671: case ST_CLOSED:
672: case ST_STOPPED:
673: FsmSendTerminateAck(fp);
674: break;
675: case ST_CLOSING:
676: case ST_STOPPING:
677: break;
678: case ST_REQSENT:
679: FsmNewState(fp, ST_ACKRCVD);
680: FsmInitRestartCounter(fp, fp->conf.maxconfig);
681: FsmInitMaxFailure(fp, fp->conf.maxfailure);
682: FsmInitMaxConfig(fp, fp->conf.maxconfig);
683: TimerStart(&fp->timer); /* Start restart timer */
684: break;
685: case ST_ACKRCVD:
686: FsmNewState(fp, ST_REQSENT);
687: FsmSendConfigReq(fp);
688: break;
689: case ST_ACKSENT:
690: FsmNewState(fp, ST_OPENED);
691: FsmInitRestartCounter(fp, fp->conf.maxconfig);
692: FsmInitMaxFailure(fp, fp->conf.maxfailure);
693: FsmInitMaxConfig(fp, fp->conf.maxconfig);
694: FsmLayerUp(fp);
695: break;
696: case ST_OPENED:
697: FsmNewState(fp, ST_REQSENT);
698: FsmLayerDown(fp);
699: FsmSendConfigReq(fp);
700: break;
701: default:
702: break;
703: }
704: mbfree(bp);
705: }
706:
707: /* RCN */
708:
709: static void
710: FsmRecvConfigNak(Fsm fp, FsmHeader lhp, Mbuf bp)
711: {
712:
713: /* Check sequence number */
714: if (lhp->id != (u_char) (fp->reqid - 1)) {
715: Log(fp->log, ("[%s] Wrong id#, expecting %d", Pref(fp), (u_char) (fp->reqid - 1)));
716: mbfree(bp);
717: return;
718: }
719:
720: /* Check and process easy cases */
721: switch (fp->state) {
722: case ST_INITIAL:
723: case ST_STARTING:
724: Log(fp->log, ("[%s] %s: Oops, RCN in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
725: mbfree(bp);
726: return;
727: case ST_CLOSED:
728: case ST_STOPPED:
729: FsmSendTerminateAck(fp);
730: mbfree(bp);
731: return;
732: case ST_CLOSING:
733: case ST_STOPPING:
734: mbfree(bp);
735: return;
736: default:
737: break;
738: }
739:
740: /* Decode packet */
741: FsmDecodeBuffer(fp, MBDATA(bp), MBLEN(bp), MODE_NAK);
742:
743: /* Not converging? */
744: if (fp->config <= 0) {
745: Log(fp->log, ("[%s] %s: not converging", Pref(fp), Fsm(fp)));
746: FsmFailure(fp, FAIL_NEGOT_FAILURE);
747: mbfree(bp);
748: return;
749: }
750:
751: /* Do whatever */
752: switch (fp->state) {
753: case ST_REQSENT:
754: case ST_ACKSENT:
755: FsmInitRestartCounter(fp, fp->conf.maxconfig);
756: FsmSendConfigReq(fp);
757: break;
758: case ST_OPENED:
759: FsmLayerDown(fp);
760: /* fall through */
761: case ST_ACKRCVD:
762: FsmNewState(fp, ST_REQSENT);
763: FsmSendConfigReq(fp);
764: break;
765: default:
766: break;
767: }
768: mbfree(bp);
769: }
770:
771: /* RCJ */
772:
773: static void
774: FsmRecvConfigRej(Fsm fp, FsmHeader lhp, Mbuf bp)
775: {
776:
777: /* Check sequence number */
778: if (lhp->id != (u_char) (fp->reqid - 1)) {
779: Log(fp->log, ("[%s] Wrong id#, expecting %d", Pref(fp), (u_char) (fp->reqid - 1)));
780: mbfree(bp);
781: return;
782: }
783:
784: /* XXX should verify contents are a subset of previously sent config-req */
785:
786: /* Check and process easy cases */
787: switch (fp->state) {
788: case ST_INITIAL:
789: case ST_STARTING:
790: Log(fp->log, ("[%s] %s: Oops, RCJ in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
791: mbfree(bp);
792: return;
793: case ST_CLOSED:
794: case ST_STOPPED:
795: FsmSendTerminateAck(fp);
796: mbfree(bp);
797: return;
798: case ST_CLOSING:
799: case ST_STOPPING:
800: mbfree(bp);
801: return;
802: default:
803: break;
804: }
805:
806: /* Decode packet */
807: FsmDecodeBuffer(fp, MBDATA(bp), MBLEN(bp), MODE_REJ);
808:
809: /* Not converging? */
810: if (fp->config <= 0) {
811: Log(fp->log, ("[%s] %s: not converging", Pref(fp), Fsm(fp)));
812: FsmFailure(fp, FAIL_NEGOT_FAILURE);
813: mbfree(bp);
814: return;
815: }
816:
817: /* Do whatever */
818: switch (fp->state) {
819: case ST_REQSENT:
820: case ST_ACKSENT:
821: FsmInitRestartCounter(fp, fp->conf.maxconfig);
822: FsmSendConfigReq(fp);
823: break;
824: case ST_OPENED:
825: FsmNewState(fp, ST_REQSENT);
826: FsmLayerDown(fp);
827: FsmSendConfigReq(fp);
828: break;
829: case ST_ACKRCVD:
830: FsmNewState(fp, ST_REQSENT);
831: FsmSendConfigReq(fp);
832: break;
833: default:
834: break;
835: }
836: mbfree(bp);
837: }
838:
839: /* RTR */
840:
841: static void
842: FsmRecvTermReq(Fsm fp, FsmHeader lhp, Mbuf bp)
843: {
1.1.1.3 ! misho 844: (void)lhp;
1.1 misho 845: if (fp->type->link_layer) {
846: RecordLinkUpDownReason(NULL, (Link)(fp->arg), 0, STR_PEER_DISC, NULL);
847: }
848: switch (fp->state) {
849: case ST_INITIAL:
850: case ST_STARTING:
851: Log(fp->log, ("[%s] %s: Oops, RTR in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
852: break;
853: case ST_CLOSED:
854: case ST_STOPPED:
855: case ST_CLOSING:
856: case ST_STOPPING:
857: case ST_REQSENT:
858: FsmSendTerminateAck(fp);
859: break;
860: case ST_ACKRCVD:
861: case ST_ACKSENT:
862: FsmNewState(fp, ST_REQSENT);
863: FsmSendTerminateAck(fp);
864: break;
865: case ST_OPENED:
866: FsmNewState(fp, ST_STOPPING);
867: FsmSendTerminateAck(fp);
868: FsmLayerDown(fp);
869: FsmInitRestartCounter(fp, 0); /* Zero restart counter */
870: TimerStart(&fp->timer); /* Start restart timer */
871: if (fp->type->UnConfigure)
872: (*fp->type->UnConfigure)(fp);
873: break;
874: }
875: mbfree(bp);
876: }
877:
878: /* RTA */
879:
880: static void
881: FsmRecvTermAck(Fsm fp, FsmHeader lhp, Mbuf bp)
882: {
1.1.1.3 ! misho 883: (void)lhp;
1.1 misho 884: switch (fp->state) {
885: case ST_CLOSING:
886: FsmNewState(fp, ST_CLOSED);
887: FsmLayerFinish(fp);
888: break;
889: case ST_STOPPING:
890: FsmNewState(fp, ST_STOPPED);
891: FsmLayerFinish(fp);
892: break;
893: case ST_ACKRCVD:
894: FsmNewState(fp, ST_REQSENT);
895: break;
896: case ST_OPENED:
897: FsmNewState(fp, ST_REQSENT);
898: FsmLayerDown(fp);
899: FsmSendConfigReq(fp);
900: break;
901: default:
902: break;
903: }
904: mbfree(bp);
905: }
906:
907: /*
908: * FsmRecvCodeRej()
909: *
910: * By default, this is fatal for most codes
911: */
912:
913: static void
914: FsmRecvCodeRej(Fsm fp, FsmHeader lhp, Mbuf bp)
915: {
916: u_char code = 0;
917: int fatal;
918:
1.1.1.3 ! misho 919: (void)lhp;
1.1 misho 920: /* Get code and log it */
921: bp = mbread(bp, &code, sizeof(code));
922: Log(fp->log, ("[%s] %s: code %s was rejected", Pref(fp), Fsm(fp), FsmCodeName(code)));
923:
924: /* Determine fatalness */
925: if (fp->type->RecvCodeRej)
926: fatal = (*fp->type->RecvCodeRej)(fp, code, bp);
927: else {
928: switch (code) {
929: case CODE_CONFIGREQ:
930: case CODE_CONFIGACK:
931: case CODE_CONFIGNAK:
932: case CODE_CONFIGREJ:
933: case CODE_TERMREQ:
934: case CODE_TERMACK:
935: case CODE_CODEREJ:
936: case CODE_PROTOREJ:
937: case CODE_ECHOREQ:
938: case CODE_ECHOREP:
939: case CODE_RESETREQ:
940: case CODE_RESETACK:
941: fatal = TRUE;
942: break;
943: case CODE_VENDOR:
944: case CODE_DISCREQ:
945: case CODE_IDENT:
946: case CODE_TIMEREM:
947: default: /* if we don't know it, that makes two of us */
948: fatal = FALSE;
949: break;
950: }
951: }
952:
953: /* Possibly shut down as a result */
954: if (fatal)
955: FsmFailure(fp, FAIL_RECD_CODEREJ); /* RXJ- */
956: else
957: FsmRecvRxjPlus(fp);
958: mbfree(bp);
959: }
960:
961: /*
962: * FsmRecvProtoRej()
963: *
964: * By default, this is non-fatal
965: */
966:
967: static void
968: FsmRecvProtoRej(Fsm fp, FsmHeader lhp, Mbuf bp)
969: {
970: u_short proto = 0;
971: int fatal = FALSE;
972:
1.1.1.3 ! misho 973: (void)lhp;
1.1 misho 974: bp = mbread(bp, &proto, sizeof(proto));
975: proto = ntohs(proto);
976: Log(fp->log, ("[%s] %s: protocol %s was rejected", Pref(fp), Fsm(fp), ProtoName(proto)));
977: if (fp->state == ST_OPENED && fp->type->RecvProtoRej)
978: fatal = (*fp->type->RecvProtoRej)(fp, proto, bp);
979: if (fatal)
980: FsmFailure(fp, FAIL_RECD_PROTREJ); /* RXJ- */
981: else
982: FsmRecvRxjPlus(fp);
983: mbfree(bp);
984: }
985:
986: /*
987: * FsmRecvRxjPlus()
988: */
989:
990: static void
991: FsmRecvRxjPlus(Fsm fp) /* RXJ+ */
992: {
993: switch (fp->state) {
994: case ST_ACKRCVD:
995: FsmNewState(fp, ST_REQSENT);
996: break;
997: default:
998: break;
999: }
1000: }
1001:
1002: /*
1003: * FsmFailure()
1004: *
1005: * Call this at any point if something fatal happens that is inherent
1006: * to the FSM itself, like a RXJ- event or negotiation failed to converge.
1007: * The action taken is like the RXJ- event.
1008: */
1009:
1010: void
1011: FsmFailure(Fsm fp, enum fsmfail reason)
1012: {
1013: Log(fp->log, ("[%s] %s: %s", Pref(fp), Fsm(fp), FsmFailureStr(reason)));
1014:
1015: /* Let layer do any special handling of error code */
1016: if (fp->type->Failure)
1017: (*fp->type->Failure)(fp, reason);
1018:
1019: /* Shut this state machine down */
1020: switch (fp->state) {
1021: case ST_CLOSING:
1022: FsmNewState(fp, ST_CLOSED);
1023: /* fall through */
1024: case ST_CLOSED:
1025: FsmLayerFinish(fp);
1026: break;
1027: case ST_STOPPING:
1028: FsmNewState(fp, ST_STOPPED);
1029: FsmLayerFinish(fp);
1030: break;
1031: case ST_ACKRCVD:
1032: case ST_ACKSENT:
1033: case ST_REQSENT:
1034: FsmNewState(fp, ST_STOPPED);
1035: if (!fp->conf.passive)
1036: FsmLayerFinish(fp);
1037: if (fp->type->UnConfigure)
1038: (*fp->type->UnConfigure)(fp);
1039: break;
1040:
1041: /*
1042: * In the opened state, the peer FSM has somehow died or did something
1043: * horribly wrong to us. So the common sense action in this case is to
1044: * bring the whole link down, rather than restarting just the FSM.
1045: * We do this by telling the lower layer to restart using tlf and tls
1046: * while also pretending that we got a DOWN event.
1047: */
1048: case ST_OPENED:
1049: FsmNewState(fp, ST_STOPPING);
1050: FsmInitRestartCounter(fp, fp->conf.maxterminate);
1051: FsmSendTerminateReq(fp);
1052: FsmLayerDown(fp);
1053: if (fp->type->UnConfigure)
1054: (*fp->type->UnConfigure)(fp);
1055: break;
1056:
1057: /*
1058: * In the STOPPED state, then most likely the negotiation timed out
1059: * or didn't converge. Just wait for the DOWN event from the previously
1060: * issued tlf action.
1061: */
1062: case ST_STOPPED:
1063: if (!fp->conf.passive)
1064: FsmLayerFinish(fp);
1065: break;
1066: default:
1067: break;
1068: }
1069: }
1070:
1071: /*
1072: * FsmFailureStr()
1073: */
1074:
1075: const char *
1076: FsmFailureStr(enum fsmfail reason)
1077: {
1078: const char *string = NULL;
1079:
1080: switch (reason) {
1081: case FAIL_NEGOT_FAILURE:
1082: string = STR_FAIL_NEGOT_FAILURE;
1083: break;
1084: case FAIL_RECD_BADMAGIC:
1085: string = STR_FAIL_RECD_BADMAGIC;
1086: break;
1087: case FAIL_RECD_CODEREJ:
1088: string = STR_FAIL_RECD_CODEREJ;
1089: break;
1090: case FAIL_RECD_PROTREJ:
1091: string = STR_FAIL_RECD_PROTREJ;
1092: break;
1093: case FAIL_WAS_PROTREJ:
1094: string = STR_FAIL_WAS_PROTREJ;
1095: break;
1096: case FAIL_ECHO_TIMEOUT:
1097: string = STR_FAIL_ECHO_TIMEOUT;
1098: break;
1099: case FAIL_CANT_ENCRYPT:
1100: string = STR_FAIL_CANT_ENCRYPT;
1101: break;
1102: default:
1103: assert(0);
1104: }
1105: return(string);
1106: }
1107:
1108: /*
1109: * FsmSendEchoReq()
1110: *
1111: * Send an echo request containing the supplied payload data.
1112: * Consumes the mbuf.
1113: */
1114:
1115: void
1116: FsmSendEchoReq(Fsm fp, Mbuf payload)
1117: {
1118: u_int32_t const self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
1119: Mbuf bp;
1120:
1121: if (fp->state != ST_OPENED)
1122: return;
1123:
1124: /* Prepend my magic number */
1125: bp = mbcopyback(payload, -(int)sizeof(self_magic), &self_magic, sizeof(self_magic));
1126:
1127: /* Send it */
1128: Log(LG_ECHO, ("[%s] %s: SendEchoReq #%d", Pref(fp), Fsm(fp), fp->echoid));
1129: FsmOutputMbuf(fp, CODE_ECHOREQ, fp->echoid++, bp);
1130: }
1131:
1132: /*
1133: * FsmSendIdent()
1134: *
1135: * Send an LCP ident packet.
1136: */
1137:
1138: void
1139: FsmSendIdent(Fsm fp, const char *ident)
1140: {
1141: u_int32_t self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
1142: const int len = strlen(ident) + 1; /* include NUL to be nice */
1143: Mbuf bp;
1144:
1145: /* Leave magic zero unless fully opened, as IDENT can be sent anytime */
1146: if (fp->state != ST_OPENED)
1147: self_magic = 0;
1148:
1149: /* Prepend my magic number */
1150: bp = mbcopyback(NULL, 0, (u_char *) &self_magic, sizeof(self_magic));
1151: bp = mbcopyback(bp, sizeof(self_magic), ident, len);
1152:
1153: /* Send it */
1.1.1.2 misho 1154: Log(fp->log2, ("[%s] %s: SendIdent #%d", Pref(fp), Fsm(fp), fp->echoid));
1155: ShowMesg(fp->log2, Pref(fp), ident, len);
1.1 misho 1156: FsmOutputMbuf(fp, CODE_IDENT, fp->echoid++, bp);
1157: }
1158:
1159: /*
1160: * FsmSendTimeRemaining()
1161: *
1162: * Send an LCP Time-Remaining packet.
1163: */
1164:
1165: void
1166: FsmSendTimeRemaining(Fsm fp, u_int seconds)
1167: {
1168: u_int32_t self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
1169: u_int32_t data = htonl(seconds);
1170: Mbuf bp;
1171:
1172: /* Leave magic zero unless fully opened, as IDENT can be sent anytime */
1173: if (fp->state != ST_OPENED)
1174: self_magic = 0;
1175:
1176: /* Prepend my magic number */
1177: bp = mbcopyback(NULL, 0, (u_char *) &self_magic, sizeof(self_magic));
1178: bp = mbcopyback(bp, sizeof(self_magic), &data, 4);
1179:
1180: /* Send it */
1.1.1.2 misho 1181: Log(fp->log2, ("[%s] %s: SendTimeRemaining #%d", Pref(fp), Fsm(fp), fp->echoid));
1182: Log(fp->log2, ("[%s] %u seconds remain", Pref(fp), seconds));
1.1 misho 1183: FsmOutputMbuf(fp, CODE_TIMEREM, fp->echoid++, bp);
1184: }
1185:
1186: /*
1187: * FsmRecvEchoReq()
1188: */
1189:
1190: static void
1191: FsmRecvEchoReq(Fsm fp, FsmHeader lhp, Mbuf bp)
1192: {
1193: u_int32_t self_magic;
1194:
1195: /* Validate magic number */
1196: bp = FsmCheckMagic(fp, bp);
1197:
1198: /* If not opened, do nothing */
1199: if (fp->state != ST_OPENED) {
1200: mbfree(bp);
1201: return;
1202: }
1203:
1204: /* Stick my magic number in there instead */
1205: self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
1206: bp = mbcopyback(bp, -(int)sizeof(self_magic), &self_magic, sizeof(self_magic));
1207:
1208: /* Send it back, preserving everything else */
1209: Log(LG_ECHO, ("[%s] %s: SendEchoRep #%d", Pref(fp), Fsm(fp), lhp->id));
1210: FsmOutputMbuf(fp, CODE_ECHOREP, lhp->id, bp);
1211: }
1212:
1213: /*
1214: * FsmRecvEchoRep()
1215: */
1216:
1217: static void
1218: FsmRecvEchoRep(Fsm fp, FsmHeader lhp, Mbuf bp)
1219: {
1.1.1.3 ! misho 1220: (void)lhp;
1.1 misho 1221: bp = FsmCheckMagic(fp, bp);
1222: mbfree(bp);
1223: }
1224:
1225: /*
1226: * FsmRecvDiscReq()
1227: */
1228:
1229: static void
1230: FsmRecvDiscReq(Fsm fp, FsmHeader lhp, Mbuf bp)
1231: {
1.1.1.3 ! misho 1232: (void)lhp;
1.1 misho 1233: bp = FsmCheckMagic(fp, bp);
1234: if (fp->type->RecvDiscReq)
1235: (*fp->type->RecvDiscReq)(fp, bp);
1236: mbfree(bp);
1237: }
1238:
1239: /*
1240: * FsmRecvIdent()
1241: */
1242:
1243: static void
1244: FsmRecvIdent(Fsm fp, FsmHeader lhp, Mbuf bp)
1245: {
1.1.1.3 ! misho 1246: (void)lhp;
1.1 misho 1247: bp = FsmCheckMagic(fp, bp);
1248: if (bp)
1249: ShowMesg(fp->log, Pref(fp), (char *) MBDATA(bp), MBLEN(bp));
1250: if (fp->type->RecvIdent)
1251: (*fp->type->RecvIdent)(fp, bp);
1252: mbfree(bp);
1253: }
1254:
1255: /*
1256: * FsmRecvVendor()
1257: */
1258:
1259: static void
1260: FsmRecvVendor(Fsm fp, FsmHeader lhp, Mbuf bp)
1261: {
1.1.1.3 ! misho 1262: (void)lhp;
1.1 misho 1263: bp = FsmCheckMagic(fp, bp);
1264: if (fp->type->RecvVendor)
1265: (*fp->type->RecvVendor)(fp, bp);
1266: mbfree(bp);
1267: }
1268:
1269: /*
1270: * FsmRecvTimeRemain()
1271: */
1272:
1273: static void
1274: FsmRecvTimeRemain(Fsm fp, FsmHeader lhp, Mbuf bp)
1275: {
1.1.1.3 ! misho 1276: (void)lhp;
1.1 misho 1277: bp = FsmCheckMagic(fp, bp);
1278: if (bp) {
1279: u_int32_t remain = 0;
1280: mbcopy(bp, 0, &remain, sizeof(remain));
1281: remain = ntohl(remain);
1282: Log(fp->log, ("[%s] %u seconds remain", Pref(fp), remain));
1283: }
1284: if (fp->type->RecvTimeRemain)
1285: (*fp->type->RecvTimeRemain)(fp, bp);
1286: mbfree(bp);
1287: }
1288:
1289: /*
1290: * FsmRecvResetReq()
1291: */
1292:
1293: static void
1294: FsmRecvResetReq(Fsm fp, FsmHeader lhp, Mbuf bp)
1295: {
1296: if (fp->type->RecvResetReq)
1297: (*fp->type->RecvResetReq)(fp, lhp->id, bp);
1298: mbfree(bp);
1299: }
1300:
1301: /*
1302: * FsmRecvResetAck()
1303: */
1304:
1305: static void
1306: FsmRecvResetAck(Fsm fp, FsmHeader lhp, Mbuf bp)
1307: {
1308: if (fp->type->RecvResetAck)
1309: (*fp->type->RecvResetAck)(fp, lhp->id, bp);
1310: mbfree(bp);
1311: }
1312:
1313: /*
1314: * FsmLayerUp()
1315: */
1316:
1317: static void
1318: FsmLayerUp(Fsm fp)
1319: {
1320: Log(fp->log2, ("[%s] %s: LayerUp", Pref(fp), Fsm(fp)));
1321: if (fp->type->LayerUp)
1322: (*fp->type->LayerUp)(fp);
1323: }
1324:
1325: /*
1326: * FsmLayerDown()
1327: */
1328:
1329: static void
1330: FsmLayerDown(Fsm fp)
1331: {
1332: Log(fp->log2, ("[%s] %s: LayerDown", Pref(fp), Fsm(fp)));
1333: if (fp->type->LayerDown)
1334: (*fp->type->LayerDown)(fp);
1335: }
1336:
1337: /*
1338: * FsmLayerStart()
1339: */
1340:
1341: static void
1342: FsmLayerStart(Fsm fp)
1343: {
1344: Log(fp->log2, ("[%s] %s: LayerStart", Pref(fp), Fsm(fp)));
1345: if (fp->type->LayerStart)
1346: (*fp->type->LayerStart)(fp);
1347: }
1348:
1349: /*
1350: * FsmLayerFinish()
1351: */
1352:
1353: static void
1354: FsmLayerFinish(Fsm fp)
1355: {
1356: Log(fp->log2, ("[%s] %s: LayerFinish", Pref(fp), Fsm(fp)));
1357: if (fp->type->LayerFinish)
1358: (*fp->type->LayerFinish)(fp);
1359: }
1360:
1361: /*
1362: * FsmCheckMagic()
1363: */
1364:
1365: static Mbuf
1366: FsmCheckMagic(Fsm fp, Mbuf bp)
1367: {
1368: u_int32_t peer_magic;
1369: u_int32_t peer_magic_ought;
1370:
1371: /* Read magic number */
1372: bp = mbread(bp, &peer_magic, sizeof(peer_magic));
1373: peer_magic = ntohl(peer_magic);
1374:
1375: /* What should magic number be? */
1376: if (PROT_LINK_LAYER(fp->type->proto))
1377: peer_magic_ought = ((Link)(fp->arg))->lcp.peer_magic;
1378: else
1379: peer_magic_ought = 0;
1380:
1381: /* Verify */
1382: if (fp->conf.check_magic && peer_magic != 0
1383: && peer_magic != peer_magic_ought) {
1384: Log(fp->log, ("[%s] %s: magic number is wrong: 0x%08x != 0x%08x",
1385: Pref(fp), Fsm(fp), peer_magic, peer_magic_ought));
1386: FsmFailure(fp, FAIL_RECD_BADMAGIC);
1387: }
1388: return(bp);
1389: }
1390:
1391: /*
1392: * FsmEchoTimeout()
1393: */
1394:
1395: static void
1396: FsmEchoTimeout(void *arg)
1397: {
1398: Fsm const fp = (Fsm) arg;
1399: Bund b;
1400: Link l;
1.1.1.3 ! misho 1401: #ifndef NG_PPP_STATS64
1.1 misho 1402: struct ng_ppp_link_stat oldStats;
1.1.1.3 ! misho 1403: #else
! 1404: struct ng_ppp_link_stat64 oldStats;
! 1405: #endif
1.1 misho 1406:
1407: if (fp->type->link_layer) {
1408: l = (Link)fp->arg;
1409: b = l->bund;
1410: } else {
1411: b = (Bund)fp->arg;
1412: l = NULL;
1413: }
1414:
1415: if (!b) {
1416: /* We can't get link stat without bundle present */
1417: return;
1418: }
1419:
1420: /* See if there was any traffic since last time */
1421: oldStats = fp->idleStats;
1.1.1.3 ! misho 1422: #ifndef NG_PPP_STATS64
1.1 misho 1423: NgFuncGetStats(b, l ?
1424: l->bundleIndex : NG_PPP_BUNDLE_LINKNUM, &fp->idleStats);
1.1.1.3 ! misho 1425: #else
! 1426: NgFuncGetStats64(b, l ?
! 1427: l->bundleIndex : NG_PPP_BUNDLE_LINKNUM, &fp->idleStats);
! 1428: #endif
1.1 misho 1429: if (fp->idleStats.recvFrames > oldStats.recvFrames)
1430: fp->quietCount = 0;
1431: else
1432: fp->quietCount++;
1433:
1434: /* See if peer hasn't responded for too many requests */
1435: switch (fp->quietCount) {
1436:
1437: /* Peer failed to reply to previous echo request */
1438: default:
1439: Log(LG_ECHO|fp->log,
1440: ("[%s] %s: no reply to %d echo request(s)",
1441: Pref(fp), Fsm(fp), fp->quietCount - 1));
1442:
1443: /* Has peer failed to reply for maximum allowable interval? */
1444: if (fp->quietCount * fp->conf.echo_int >= fp->conf.echo_max) {
1445: TimerStop(&fp->echoTimer);
1446: FsmFailure(fp, FAIL_ECHO_TIMEOUT);
1447: break;
1448: }
1449: /* fall through */
1450: case 1: /* one interval of silence elapsed; send first echo request */
1451: FsmSendEchoReq(fp, NULL);
1452: /* fall through */
1453: case 0:
1454: break;
1455: }
1456: }
1457:
1458: /*
1459: * FsmInput()
1460: *
1461: * Deal with an incoming packet for FSM pointed to by "fp"
1462: */
1463:
1464: void
1465: FsmInput(Fsm fp, Mbuf bp)
1466: {
1.1.1.3 ! misho 1467: int log;
! 1468: unsigned length, recd_len;
1.1 misho 1469: struct fsmheader hdr;
1470:
1471: /* Check for runt frames; discard them */
1472: if ((recd_len = MBLEN(bp)) < sizeof(hdr)) {
1.1.1.3 ! misho 1473: Log(fp->log, ("[%s] %s: runt packet: %u bytes", Pref(fp), Fsm(fp), recd_len));
1.1 misho 1474: mbfree(bp);
1475: return;
1476: }
1477:
1478: /* Read in the header */
1479: bp = mbread(bp, &hdr, sizeof(hdr));
1480: length = ntohs(hdr.length);
1481:
1482: /* Make sure length is sensible; discard otherwise */
1483: if (length < sizeof(hdr) || length > recd_len) {
1.1.1.3 ! misho 1484: Log(fp->log, ("[%s] %s: bad length: says %u, rec'd %u",
1.1 misho 1485: Pref(fp), Fsm(fp), length, recd_len));
1486: mbfree(bp);
1487: return;
1488: }
1489:
1490: /* Truncate off any padding bytes */
1491: if (length < recd_len)
1492: bp = mbtrunc(bp, length - sizeof(hdr));
1493:
1494: /* Check for a valid code byte -- if not, send code-reject */
1495: if ((hdr.code >= NUM_FSM_CODES) ||
1496: (((1 << hdr.code) & fp->type->known_codes) == 0)) { /* RUC */
1497: Log(fp->log, ("[%s] %s: unknown code %d", Pref(fp), Fsm(fp), hdr.code));
1498: FsmOutputMbuf(fp, CODE_CODEREJ, fp->rejid++, bp);
1499: return;
1500: }
1501:
1502: /* Log it */
1503: if (hdr.code == CODE_ECHOREQ || hdr.code == CODE_ECHOREP)
1504: log = LG_ECHO;
1505: else if (hdr.code == CODE_RESETREQ || hdr.code == CODE_RESETACK)
1506: log = fp->log2;
1507: else
1508: log = fp->log;
1509: Log(log, ("[%s] %s: rec'd %s #%d (%s)",
1510: Pref(fp), Fsm(fp), FsmCodeName(hdr.code), (int) hdr.id,
1511: FsmStateName(fp->state)));
1512:
1513: /* Do whatever */
1514: (*FsmCodes[hdr.code].action)(fp, &hdr, bp);
1515: }
1516:
1517: /*
1518: * FsmConfValue()
1519: *
1520: * Write in a configuration item with "len" bytes of information.
1521: * Special cases: length -2 or -4 means convert to network byte order.
1522: */
1523:
1524: u_char *
1525: FsmConfValue(u_char *cp, int type, int len, const void *data)
1526: {
1.1.1.3 ! misho 1527: const u_char *bytes = (const u_char *) data;
1.1 misho 1528: u_int16_t sv;
1529: u_int32_t lv;
1530:
1531: /* Special cases */
1532: switch (len) {
1533: case -2:
1534: len = 2;
1.1.1.3 ! misho 1535: sv = htons(*((const u_int16_t *) data));
1.1 misho 1536: bytes = (u_char *) &sv;
1537: break;
1538: case -4:
1539: len = 4;
1.1.1.3 ! misho 1540: lv = htonl(*((const u_int32_t *) data));
1.1 misho 1541: bytes = (u_char *) &lv;
1542: break;
1543: default:
1544: break;
1545: }
1546:
1547: /* Add header and data */
1548: *cp++ = type;
1549: *cp++ = len + 2;
1550: while (len-- > 0)
1551: *cp++ = *bytes++;
1552:
1553: /* Done */
1554: return(cp);
1555: }
1556:
1557: /*
1558: * FsmExtractOptions()
1559: *
1560: * Extract options from a config packet
1561: */
1562:
1563: static int
1564: FsmExtractOptions(Fsm fp, u_char *data, int dlen, FsmOption opts, int max)
1565: {
1566: int num;
1567:
1568: for (num = 0; dlen >= 2 && num < max; num++) {
1569: FsmOption const opt = &opts[num];
1570:
1571: opt->type = data[0];
1572: opt->len = data[1];
1573: opt->data = &data[2];
1574: if (opt->len < 2 || opt->len > dlen)
1575: break;
1576: data += opt->len;
1577: dlen -= opt->len;
1578: }
1579: if (dlen != 0)
1580: LogDumpBuf(LG_ERR, data, dlen,
1581: "[%s] %s: %d extra garbage bytes in config packet", Pref(fp), Fsm(fp), dlen);
1582: return(num);
1583: }
1584:
1585: /*
1586: * FsmFindOption()
1587: */
1588:
1589: FsmOptInfo
1590: FsmFindOptInfo(FsmOptInfo list, u_char type)
1591: {
1592: for (; list->name; list++)
1593: if (list->type == type)
1594: return(list);
1595: return(NULL);
1596: }
1597:
1598: /*
1599: * FsmDecodeBuffer()
1600: */
1601:
1602: static void
1603: FsmDecodeBuffer(Fsm fp, u_char *buf, int size, int mode)
1604: {
1605: struct fsmoption opts[FSM_MAX_OPTS];
1606: int num;
1607:
1608: if (mode == MODE_REQ)
1609: gAckSize = gNakSize = gRejSize = 0;
1610: num = FsmExtractOptions(fp, buf, size, opts, FSM_MAX_OPTS);
1611: (*fp->type->DecodeConfig)(fp, opts, num, mode);
1612: }
1613:
1614: /*
1615: * FsmAck()
1616: */
1617:
1618: void
1619: FsmAck(Fsm fp, const struct fsmoption *opt)
1620: {
1621: if (gAckSize + opt->len > sizeof(gAckBuf)) {
1622: Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "ack"));
1623: return;
1624: }
1625: memcpy(&gAckBuf[gAckSize], opt, 2);
1626: memcpy(&gAckBuf[gAckSize + 2], opt->data, opt->len - 2);
1627: gAckSize += opt->len;
1628: }
1629:
1630: /*
1631: * FsmNak()
1632: */
1633:
1634: void
1635: FsmNak(Fsm fp, const struct fsmoption *opt)
1636: {
1637: if (gNakSize + opt->len > sizeof(gNakBuf)) {
1638: Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "nak"));
1639: return;
1640: }
1641: memcpy(&gNakBuf[gNakSize], opt, 2);
1642: memcpy(&gNakBuf[gNakSize + 2], opt->data, opt->len - 2);
1643: gNakSize += opt->len;
1644: }
1645:
1646: /*
1647: * FsmRej()
1648: */
1649:
1650: void
1651: FsmRej(Fsm fp, const struct fsmoption *opt)
1652: {
1653: if (gRejSize + opt->len > sizeof(gRejBuf)) {
1654: Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "rej"));
1655: return;
1656: }
1657: memcpy(&gRejBuf[gRejSize], opt, 2);
1658: memcpy(&gRejBuf[gRejSize + 2], opt->data, opt->len - 2);
1659: gRejSize += opt->len;
1660: }
1661:
1662: /*
1663: * FsmCodeName()
1664: */
1665:
1666: const char *
1667: FsmCodeName(int code)
1668: {
1.1.1.3 ! misho 1669: if (code >= 0 && code < (int)NUM_FSM_CODES)
1.1 misho 1670: return (FsmCodes[code].name);
1671: return ("UNKNOWN");
1672: }
1673:
1674: /*
1675: * FsmStateName()
1676: */
1677:
1678: const char *
1679: FsmStateName(enum fsm_state state)
1680: {
1681: switch (state) {
1682: case ST_INITIAL: return "Initial";
1683: case ST_STARTING: return "Starting";
1684: case ST_CLOSED: return "Closed";
1685: case ST_STOPPED: return "Stopped";
1686: case ST_CLOSING: return "Closing";
1687: case ST_STOPPING: return "Stopping";
1688: case ST_REQSENT: return "Req-Sent";
1689: case ST_ACKRCVD: return "Ack-Rcvd";
1690: case ST_ACKSENT: return "Ack-Sent";
1691: case ST_OPENED: return "Opened";
1692: }
1693: return "???";
1694: }
1695:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>