Annotation of embedaddon/mpd/src/fsm.c, revision 1.1.1.1
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: {
844: if (fp->type->link_layer) {
845: RecordLinkUpDownReason(NULL, (Link)(fp->arg), 0, STR_PEER_DISC, NULL);
846: }
847: switch (fp->state) {
848: case ST_INITIAL:
849: case ST_STARTING:
850: Log(fp->log, ("[%s] %s: Oops, RTR in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
851: break;
852: case ST_CLOSED:
853: case ST_STOPPED:
854: case ST_CLOSING:
855: case ST_STOPPING:
856: case ST_REQSENT:
857: FsmSendTerminateAck(fp);
858: break;
859: case ST_ACKRCVD:
860: case ST_ACKSENT:
861: FsmNewState(fp, ST_REQSENT);
862: FsmSendTerminateAck(fp);
863: break;
864: case ST_OPENED:
865: FsmNewState(fp, ST_STOPPING);
866: FsmSendTerminateAck(fp);
867: FsmLayerDown(fp);
868: FsmInitRestartCounter(fp, 0); /* Zero restart counter */
869: TimerStart(&fp->timer); /* Start restart timer */
870: if (fp->type->UnConfigure)
871: (*fp->type->UnConfigure)(fp);
872: break;
873: }
874: mbfree(bp);
875: }
876:
877: /* RTA */
878:
879: static void
880: FsmRecvTermAck(Fsm fp, FsmHeader lhp, Mbuf bp)
881: {
882: switch (fp->state) {
883: case ST_CLOSING:
884: FsmNewState(fp, ST_CLOSED);
885: FsmLayerFinish(fp);
886: break;
887: case ST_STOPPING:
888: FsmNewState(fp, ST_STOPPED);
889: FsmLayerFinish(fp);
890: break;
891: case ST_ACKRCVD:
892: FsmNewState(fp, ST_REQSENT);
893: break;
894: case ST_OPENED:
895: FsmNewState(fp, ST_REQSENT);
896: FsmLayerDown(fp);
897: FsmSendConfigReq(fp);
898: break;
899: default:
900: break;
901: }
902: mbfree(bp);
903: }
904:
905: /*
906: * FsmRecvCodeRej()
907: *
908: * By default, this is fatal for most codes
909: */
910:
911: static void
912: FsmRecvCodeRej(Fsm fp, FsmHeader lhp, Mbuf bp)
913: {
914: u_char code = 0;
915: int fatal;
916:
917: /* Get code and log it */
918: bp = mbread(bp, &code, sizeof(code));
919: Log(fp->log, ("[%s] %s: code %s was rejected", Pref(fp), Fsm(fp), FsmCodeName(code)));
920:
921: /* Determine fatalness */
922: if (fp->type->RecvCodeRej)
923: fatal = (*fp->type->RecvCodeRej)(fp, code, bp);
924: else {
925: switch (code) {
926: case CODE_CONFIGREQ:
927: case CODE_CONFIGACK:
928: case CODE_CONFIGNAK:
929: case CODE_CONFIGREJ:
930: case CODE_TERMREQ:
931: case CODE_TERMACK:
932: case CODE_CODEREJ:
933: case CODE_PROTOREJ:
934: case CODE_ECHOREQ:
935: case CODE_ECHOREP:
936: case CODE_RESETREQ:
937: case CODE_RESETACK:
938: fatal = TRUE;
939: break;
940: case CODE_VENDOR:
941: case CODE_DISCREQ:
942: case CODE_IDENT:
943: case CODE_TIMEREM:
944: default: /* if we don't know it, that makes two of us */
945: fatal = FALSE;
946: break;
947: }
948: }
949:
950: /* Possibly shut down as a result */
951: if (fatal)
952: FsmFailure(fp, FAIL_RECD_CODEREJ); /* RXJ- */
953: else
954: FsmRecvRxjPlus(fp);
955: mbfree(bp);
956: }
957:
958: /*
959: * FsmRecvProtoRej()
960: *
961: * By default, this is non-fatal
962: */
963:
964: static void
965: FsmRecvProtoRej(Fsm fp, FsmHeader lhp, Mbuf bp)
966: {
967: u_short proto = 0;
968: int fatal = FALSE;
969:
970: bp = mbread(bp, &proto, sizeof(proto));
971: proto = ntohs(proto);
972: Log(fp->log, ("[%s] %s: protocol %s was rejected", Pref(fp), Fsm(fp), ProtoName(proto)));
973: if (fp->state == ST_OPENED && fp->type->RecvProtoRej)
974: fatal = (*fp->type->RecvProtoRej)(fp, proto, bp);
975: if (fatal)
976: FsmFailure(fp, FAIL_RECD_PROTREJ); /* RXJ- */
977: else
978: FsmRecvRxjPlus(fp);
979: mbfree(bp);
980: }
981:
982: /*
983: * FsmRecvRxjPlus()
984: */
985:
986: static void
987: FsmRecvRxjPlus(Fsm fp) /* RXJ+ */
988: {
989: switch (fp->state) {
990: case ST_ACKRCVD:
991: FsmNewState(fp, ST_REQSENT);
992: break;
993: default:
994: break;
995: }
996: }
997:
998: /*
999: * FsmFailure()
1000: *
1001: * Call this at any point if something fatal happens that is inherent
1002: * to the FSM itself, like a RXJ- event or negotiation failed to converge.
1003: * The action taken is like the RXJ- event.
1004: */
1005:
1006: void
1007: FsmFailure(Fsm fp, enum fsmfail reason)
1008: {
1009: Log(fp->log, ("[%s] %s: %s", Pref(fp), Fsm(fp), FsmFailureStr(reason)));
1010:
1011: /* Let layer do any special handling of error code */
1012: if (fp->type->Failure)
1013: (*fp->type->Failure)(fp, reason);
1014:
1015: /* Shut this state machine down */
1016: switch (fp->state) {
1017: case ST_CLOSING:
1018: FsmNewState(fp, ST_CLOSED);
1019: /* fall through */
1020: case ST_CLOSED:
1021: FsmLayerFinish(fp);
1022: break;
1023: case ST_STOPPING:
1024: FsmNewState(fp, ST_STOPPED);
1025: FsmLayerFinish(fp);
1026: break;
1027: case ST_ACKRCVD:
1028: case ST_ACKSENT:
1029: case ST_REQSENT:
1030: FsmNewState(fp, ST_STOPPED);
1031: if (!fp->conf.passive)
1032: FsmLayerFinish(fp);
1033: if (fp->type->UnConfigure)
1034: (*fp->type->UnConfigure)(fp);
1035: break;
1036:
1037: /*
1038: * In the opened state, the peer FSM has somehow died or did something
1039: * horribly wrong to us. So the common sense action in this case is to
1040: * bring the whole link down, rather than restarting just the FSM.
1041: * We do this by telling the lower layer to restart using tlf and tls
1042: * while also pretending that we got a DOWN event.
1043: */
1044: case ST_OPENED:
1045: FsmNewState(fp, ST_STOPPING);
1046: FsmInitRestartCounter(fp, fp->conf.maxterminate);
1047: FsmSendTerminateReq(fp);
1048: FsmLayerDown(fp);
1049: if (fp->type->UnConfigure)
1050: (*fp->type->UnConfigure)(fp);
1051: break;
1052:
1053: /*
1054: * In the STOPPED state, then most likely the negotiation timed out
1055: * or didn't converge. Just wait for the DOWN event from the previously
1056: * issued tlf action.
1057: */
1058: case ST_STOPPED:
1059: if (!fp->conf.passive)
1060: FsmLayerFinish(fp);
1061: break;
1062: default:
1063: break;
1064: }
1065: }
1066:
1067: /*
1068: * FsmFailureStr()
1069: */
1070:
1071: const char *
1072: FsmFailureStr(enum fsmfail reason)
1073: {
1074: const char *string = NULL;
1075:
1076: switch (reason) {
1077: case FAIL_NEGOT_FAILURE:
1078: string = STR_FAIL_NEGOT_FAILURE;
1079: break;
1080: case FAIL_RECD_BADMAGIC:
1081: string = STR_FAIL_RECD_BADMAGIC;
1082: break;
1083: case FAIL_RECD_CODEREJ:
1084: string = STR_FAIL_RECD_CODEREJ;
1085: break;
1086: case FAIL_RECD_PROTREJ:
1087: string = STR_FAIL_RECD_PROTREJ;
1088: break;
1089: case FAIL_WAS_PROTREJ:
1090: string = STR_FAIL_WAS_PROTREJ;
1091: break;
1092: case FAIL_ECHO_TIMEOUT:
1093: string = STR_FAIL_ECHO_TIMEOUT;
1094: break;
1095: case FAIL_CANT_ENCRYPT:
1096: string = STR_FAIL_CANT_ENCRYPT;
1097: break;
1098: default:
1099: assert(0);
1100: }
1101: return(string);
1102: }
1103:
1104: /*
1105: * FsmSendEchoReq()
1106: *
1107: * Send an echo request containing the supplied payload data.
1108: * Consumes the mbuf.
1109: */
1110:
1111: void
1112: FsmSendEchoReq(Fsm fp, Mbuf payload)
1113: {
1114: u_int32_t const self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
1115: Mbuf bp;
1116:
1117: if (fp->state != ST_OPENED)
1118: return;
1119:
1120: /* Prepend my magic number */
1121: bp = mbcopyback(payload, -(int)sizeof(self_magic), &self_magic, sizeof(self_magic));
1122:
1123: /* Send it */
1124: Log(LG_ECHO, ("[%s] %s: SendEchoReq #%d", Pref(fp), Fsm(fp), fp->echoid));
1125: FsmOutputMbuf(fp, CODE_ECHOREQ, fp->echoid++, bp);
1126: }
1127:
1128: /*
1129: * FsmSendIdent()
1130: *
1131: * Send an LCP ident packet.
1132: */
1133:
1134: void
1135: FsmSendIdent(Fsm fp, const char *ident)
1136: {
1137: u_int32_t self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
1138: const int len = strlen(ident) + 1; /* include NUL to be nice */
1139: Mbuf bp;
1140:
1141: /* Leave magic zero unless fully opened, as IDENT can be sent anytime */
1142: if (fp->state != ST_OPENED)
1143: self_magic = 0;
1144:
1145: /* Prepend my magic number */
1146: bp = mbcopyback(NULL, 0, (u_char *) &self_magic, sizeof(self_magic));
1147: bp = mbcopyback(bp, sizeof(self_magic), ident, len);
1148:
1149: /* Send it */
1150: Log(LG_FSM, ("[%s] %s: SendIdent #%d", Pref(fp), Fsm(fp), fp->echoid));
1151: ShowMesg(LG_FSM, Pref(fp), ident, len);
1152: FsmOutputMbuf(fp, CODE_IDENT, fp->echoid++, bp);
1153: }
1154:
1155: /*
1156: * FsmSendTimeRemaining()
1157: *
1158: * Send an LCP Time-Remaining packet.
1159: */
1160:
1161: void
1162: FsmSendTimeRemaining(Fsm fp, u_int seconds)
1163: {
1164: u_int32_t self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
1165: u_int32_t data = htonl(seconds);
1166: Mbuf bp;
1167:
1168: /* Leave magic zero unless fully opened, as IDENT can be sent anytime */
1169: if (fp->state != ST_OPENED)
1170: self_magic = 0;
1171:
1172: /* Prepend my magic number */
1173: bp = mbcopyback(NULL, 0, (u_char *) &self_magic, sizeof(self_magic));
1174: bp = mbcopyback(bp, sizeof(self_magic), &data, 4);
1175:
1176: /* Send it */
1177: Log(LG_FSM, ("[%s] %s: SendTimeRemaining #%d", Pref(fp), Fsm(fp), fp->echoid));
1178: Log(LG_FSM, ("[%s] %u seconds remain", Pref(fp), seconds));
1179: FsmOutputMbuf(fp, CODE_TIMEREM, fp->echoid++, bp);
1180: }
1181:
1182: /*
1183: * FsmRecvEchoReq()
1184: */
1185:
1186: static void
1187: FsmRecvEchoReq(Fsm fp, FsmHeader lhp, Mbuf bp)
1188: {
1189: u_int32_t self_magic;
1190:
1191: /* Validate magic number */
1192: bp = FsmCheckMagic(fp, bp);
1193:
1194: /* If not opened, do nothing */
1195: if (fp->state != ST_OPENED) {
1196: mbfree(bp);
1197: return;
1198: }
1199:
1200: /* Stick my magic number in there instead */
1201: self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
1202: bp = mbcopyback(bp, -(int)sizeof(self_magic), &self_magic, sizeof(self_magic));
1203:
1204: /* Send it back, preserving everything else */
1205: Log(LG_ECHO, ("[%s] %s: SendEchoRep #%d", Pref(fp), Fsm(fp), lhp->id));
1206: FsmOutputMbuf(fp, CODE_ECHOREP, lhp->id, bp);
1207: }
1208:
1209: /*
1210: * FsmRecvEchoRep()
1211: */
1212:
1213: static void
1214: FsmRecvEchoRep(Fsm fp, FsmHeader lhp, Mbuf bp)
1215: {
1216: bp = FsmCheckMagic(fp, bp);
1217: mbfree(bp);
1218: }
1219:
1220: /*
1221: * FsmRecvDiscReq()
1222: */
1223:
1224: static void
1225: FsmRecvDiscReq(Fsm fp, FsmHeader lhp, Mbuf bp)
1226: {
1227: bp = FsmCheckMagic(fp, bp);
1228: if (fp->type->RecvDiscReq)
1229: (*fp->type->RecvDiscReq)(fp, bp);
1230: mbfree(bp);
1231: }
1232:
1233: /*
1234: * FsmRecvIdent()
1235: */
1236:
1237: static void
1238: FsmRecvIdent(Fsm fp, FsmHeader lhp, Mbuf bp)
1239: {
1240: bp = FsmCheckMagic(fp, bp);
1241: if (bp)
1242: ShowMesg(fp->log, Pref(fp), (char *) MBDATA(bp), MBLEN(bp));
1243: if (fp->type->RecvIdent)
1244: (*fp->type->RecvIdent)(fp, bp);
1245: mbfree(bp);
1246: }
1247:
1248: /*
1249: * FsmRecvVendor()
1250: */
1251:
1252: static void
1253: FsmRecvVendor(Fsm fp, FsmHeader lhp, Mbuf bp)
1254: {
1255: bp = FsmCheckMagic(fp, bp);
1256: if (fp->type->RecvVendor)
1257: (*fp->type->RecvVendor)(fp, bp);
1258: mbfree(bp);
1259: }
1260:
1261: /*
1262: * FsmRecvTimeRemain()
1263: */
1264:
1265: static void
1266: FsmRecvTimeRemain(Fsm fp, FsmHeader lhp, Mbuf bp)
1267: {
1268: bp = FsmCheckMagic(fp, bp);
1269: if (bp) {
1270: u_int32_t remain = 0;
1271: mbcopy(bp, 0, &remain, sizeof(remain));
1272: remain = ntohl(remain);
1273: Log(fp->log, ("[%s] %u seconds remain", Pref(fp), remain));
1274: }
1275: if (fp->type->RecvTimeRemain)
1276: (*fp->type->RecvTimeRemain)(fp, bp);
1277: mbfree(bp);
1278: }
1279:
1280: /*
1281: * FsmRecvResetReq()
1282: */
1283:
1284: static void
1285: FsmRecvResetReq(Fsm fp, FsmHeader lhp, Mbuf bp)
1286: {
1287: if (fp->type->RecvResetReq)
1288: (*fp->type->RecvResetReq)(fp, lhp->id, bp);
1289: mbfree(bp);
1290: }
1291:
1292: /*
1293: * FsmRecvResetAck()
1294: */
1295:
1296: static void
1297: FsmRecvResetAck(Fsm fp, FsmHeader lhp, Mbuf bp)
1298: {
1299: if (fp->type->RecvResetAck)
1300: (*fp->type->RecvResetAck)(fp, lhp->id, bp);
1301: mbfree(bp);
1302: }
1303:
1304: /*
1305: * FsmLayerUp()
1306: */
1307:
1308: static void
1309: FsmLayerUp(Fsm fp)
1310: {
1311: Log(fp->log2, ("[%s] %s: LayerUp", Pref(fp), Fsm(fp)));
1312: if (fp->type->LayerUp)
1313: (*fp->type->LayerUp)(fp);
1314: }
1315:
1316: /*
1317: * FsmLayerDown()
1318: */
1319:
1320: static void
1321: FsmLayerDown(Fsm fp)
1322: {
1323: Log(fp->log2, ("[%s] %s: LayerDown", Pref(fp), Fsm(fp)));
1324: if (fp->type->LayerDown)
1325: (*fp->type->LayerDown)(fp);
1326: }
1327:
1328: /*
1329: * FsmLayerStart()
1330: */
1331:
1332: static void
1333: FsmLayerStart(Fsm fp)
1334: {
1335: Log(fp->log2, ("[%s] %s: LayerStart", Pref(fp), Fsm(fp)));
1336: if (fp->type->LayerStart)
1337: (*fp->type->LayerStart)(fp);
1338: }
1339:
1340: /*
1341: * FsmLayerFinish()
1342: */
1343:
1344: static void
1345: FsmLayerFinish(Fsm fp)
1346: {
1347: Log(fp->log2, ("[%s] %s: LayerFinish", Pref(fp), Fsm(fp)));
1348: if (fp->type->LayerFinish)
1349: (*fp->type->LayerFinish)(fp);
1350: }
1351:
1352: /*
1353: * FsmCheckMagic()
1354: */
1355:
1356: static Mbuf
1357: FsmCheckMagic(Fsm fp, Mbuf bp)
1358: {
1359: u_int32_t peer_magic;
1360: u_int32_t peer_magic_ought;
1361:
1362: /* Read magic number */
1363: bp = mbread(bp, &peer_magic, sizeof(peer_magic));
1364: peer_magic = ntohl(peer_magic);
1365:
1366: /* What should magic number be? */
1367: if (PROT_LINK_LAYER(fp->type->proto))
1368: peer_magic_ought = ((Link)(fp->arg))->lcp.peer_magic;
1369: else
1370: peer_magic_ought = 0;
1371:
1372: /* Verify */
1373: if (fp->conf.check_magic && peer_magic != 0
1374: && peer_magic != peer_magic_ought) {
1375: Log(fp->log, ("[%s] %s: magic number is wrong: 0x%08x != 0x%08x",
1376: Pref(fp), Fsm(fp), peer_magic, peer_magic_ought));
1377: FsmFailure(fp, FAIL_RECD_BADMAGIC);
1378: }
1379: return(bp);
1380: }
1381:
1382: /*
1383: * FsmEchoTimeout()
1384: */
1385:
1386: static void
1387: FsmEchoTimeout(void *arg)
1388: {
1389: Fsm const fp = (Fsm) arg;
1390: Bund b;
1391: Link l;
1392: struct ng_ppp_link_stat oldStats;
1393:
1394: if (fp->type->link_layer) {
1395: l = (Link)fp->arg;
1396: b = l->bund;
1397: } else {
1398: b = (Bund)fp->arg;
1399: l = NULL;
1400: }
1401:
1402: if (!b) {
1403: /* We can't get link stat without bundle present */
1404: return;
1405: }
1406:
1407: /* See if there was any traffic since last time */
1408: oldStats = fp->idleStats;
1409: NgFuncGetStats(b, l ?
1410: l->bundleIndex : NG_PPP_BUNDLE_LINKNUM, &fp->idleStats);
1411: if (fp->idleStats.recvFrames > oldStats.recvFrames)
1412: fp->quietCount = 0;
1413: else
1414: fp->quietCount++;
1415:
1416: /* See if peer hasn't responded for too many requests */
1417: switch (fp->quietCount) {
1418:
1419: /* Peer failed to reply to previous echo request */
1420: default:
1421: Log(LG_ECHO|fp->log,
1422: ("[%s] %s: no reply to %d echo request(s)",
1423: Pref(fp), Fsm(fp), fp->quietCount - 1));
1424:
1425: /* Has peer failed to reply for maximum allowable interval? */
1426: if (fp->quietCount * fp->conf.echo_int >= fp->conf.echo_max) {
1427: TimerStop(&fp->echoTimer);
1428: FsmFailure(fp, FAIL_ECHO_TIMEOUT);
1429: break;
1430: }
1431: /* fall through */
1432: case 1: /* one interval of silence elapsed; send first echo request */
1433: FsmSendEchoReq(fp, NULL);
1434: /* fall through */
1435: case 0:
1436: break;
1437: }
1438: }
1439:
1440: /*
1441: * FsmInput()
1442: *
1443: * Deal with an incoming packet for FSM pointed to by "fp"
1444: */
1445:
1446: void
1447: FsmInput(Fsm fp, Mbuf bp)
1448: {
1449: int log, recd_len, length;
1450: struct fsmheader hdr;
1451:
1452: /* Check for runt frames; discard them */
1453: if ((recd_len = MBLEN(bp)) < sizeof(hdr)) {
1454: Log(fp->log, ("[%s] %s: runt packet: %d bytes", Pref(fp), Fsm(fp), recd_len));
1455: mbfree(bp);
1456: return;
1457: }
1458:
1459: /* Read in the header */
1460: bp = mbread(bp, &hdr, sizeof(hdr));
1461: length = ntohs(hdr.length);
1462:
1463: /* Make sure length is sensible; discard otherwise */
1464: if (length < sizeof(hdr) || length > recd_len) {
1465: Log(fp->log, ("[%s] %s: bad length: says %d, rec'd %d",
1466: Pref(fp), Fsm(fp), length, recd_len));
1467: mbfree(bp);
1468: return;
1469: }
1470:
1471: /* Truncate off any padding bytes */
1472: if (length < recd_len)
1473: bp = mbtrunc(bp, length - sizeof(hdr));
1474:
1475: /* Check for a valid code byte -- if not, send code-reject */
1476: if ((hdr.code >= NUM_FSM_CODES) ||
1477: (((1 << hdr.code) & fp->type->known_codes) == 0)) { /* RUC */
1478: Log(fp->log, ("[%s] %s: unknown code %d", Pref(fp), Fsm(fp), hdr.code));
1479: FsmOutputMbuf(fp, CODE_CODEREJ, fp->rejid++, bp);
1480: return;
1481: }
1482:
1483: /* Log it */
1484: if (hdr.code == CODE_ECHOREQ || hdr.code == CODE_ECHOREP)
1485: log = LG_ECHO;
1486: else if (hdr.code == CODE_RESETREQ || hdr.code == CODE_RESETACK)
1487: log = fp->log2;
1488: else
1489: log = fp->log;
1490: Log(log, ("[%s] %s: rec'd %s #%d (%s)",
1491: Pref(fp), Fsm(fp), FsmCodeName(hdr.code), (int) hdr.id,
1492: FsmStateName(fp->state)));
1493:
1494: /* Do whatever */
1495: (*FsmCodes[hdr.code].action)(fp, &hdr, bp);
1496: }
1497:
1498: /*
1499: * FsmConfValue()
1500: *
1501: * Write in a configuration item with "len" bytes of information.
1502: * Special cases: length -2 or -4 means convert to network byte order.
1503: */
1504:
1505: u_char *
1506: FsmConfValue(u_char *cp, int type, int len, const void *data)
1507: {
1508: u_char *bytes = (u_char *) data;
1509: u_int16_t sv;
1510: u_int32_t lv;
1511:
1512: /* Special cases */
1513: switch (len) {
1514: case -2:
1515: len = 2;
1516: sv = htons(*((u_int16_t *) data));
1517: bytes = (u_char *) &sv;
1518: break;
1519: case -4:
1520: len = 4;
1521: lv = htonl(*((u_int32_t *) data));
1522: bytes = (u_char *) &lv;
1523: break;
1524: default:
1525: break;
1526: }
1527:
1528: /* Add header and data */
1529: *cp++ = type;
1530: *cp++ = len + 2;
1531: while (len-- > 0)
1532: *cp++ = *bytes++;
1533:
1534: /* Done */
1535: return(cp);
1536: }
1537:
1538: /*
1539: * FsmExtractOptions()
1540: *
1541: * Extract options from a config packet
1542: */
1543:
1544: static int
1545: FsmExtractOptions(Fsm fp, u_char *data, int dlen, FsmOption opts, int max)
1546: {
1547: int num;
1548:
1549: for (num = 0; dlen >= 2 && num < max; num++) {
1550: FsmOption const opt = &opts[num];
1551:
1552: opt->type = data[0];
1553: opt->len = data[1];
1554: opt->data = &data[2];
1555: if (opt->len < 2 || opt->len > dlen)
1556: break;
1557: data += opt->len;
1558: dlen -= opt->len;
1559: }
1560: if (dlen != 0)
1561: LogDumpBuf(LG_ERR, data, dlen,
1562: "[%s] %s: %d extra garbage bytes in config packet", Pref(fp), Fsm(fp), dlen);
1563: return(num);
1564: }
1565:
1566: /*
1567: * FsmFindOption()
1568: */
1569:
1570: FsmOptInfo
1571: FsmFindOptInfo(FsmOptInfo list, u_char type)
1572: {
1573: for (; list->name; list++)
1574: if (list->type == type)
1575: return(list);
1576: return(NULL);
1577: }
1578:
1579: /*
1580: * FsmDecodeBuffer()
1581: */
1582:
1583: static void
1584: FsmDecodeBuffer(Fsm fp, u_char *buf, int size, int mode)
1585: {
1586: struct fsmoption opts[FSM_MAX_OPTS];
1587: int num;
1588:
1589: if (mode == MODE_REQ)
1590: gAckSize = gNakSize = gRejSize = 0;
1591: num = FsmExtractOptions(fp, buf, size, opts, FSM_MAX_OPTS);
1592: (*fp->type->DecodeConfig)(fp, opts, num, mode);
1593: }
1594:
1595: /*
1596: * FsmAck()
1597: */
1598:
1599: void
1600: FsmAck(Fsm fp, const struct fsmoption *opt)
1601: {
1602: if (gAckSize + opt->len > sizeof(gAckBuf)) {
1603: Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "ack"));
1604: return;
1605: }
1606: memcpy(&gAckBuf[gAckSize], opt, 2);
1607: memcpy(&gAckBuf[gAckSize + 2], opt->data, opt->len - 2);
1608: gAckSize += opt->len;
1609: }
1610:
1611: /*
1612: * FsmNak()
1613: */
1614:
1615: void
1616: FsmNak(Fsm fp, const struct fsmoption *opt)
1617: {
1618: if (gNakSize + opt->len > sizeof(gNakBuf)) {
1619: Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "nak"));
1620: return;
1621: }
1622: memcpy(&gNakBuf[gNakSize], opt, 2);
1623: memcpy(&gNakBuf[gNakSize + 2], opt->data, opt->len - 2);
1624: gNakSize += opt->len;
1625: }
1626:
1627: /*
1628: * FsmRej()
1629: */
1630:
1631: void
1632: FsmRej(Fsm fp, const struct fsmoption *opt)
1633: {
1634: if (gRejSize + opt->len > sizeof(gRejBuf)) {
1635: Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "rej"));
1636: return;
1637: }
1638: memcpy(&gRejBuf[gRejSize], opt, 2);
1639: memcpy(&gRejBuf[gRejSize + 2], opt->data, opt->len - 2);
1640: gRejSize += opt->len;
1641: }
1642:
1643: /*
1644: * FsmCodeName()
1645: */
1646:
1647: const char *
1648: FsmCodeName(int code)
1649: {
1650: if (code >= 0 && code < NUM_FSM_CODES)
1651: return (FsmCodes[code].name);
1652: return ("UNKNOWN");
1653: }
1654:
1655: /*
1656: * FsmStateName()
1657: */
1658:
1659: const char *
1660: FsmStateName(enum fsm_state state)
1661: {
1662: switch (state) {
1663: case ST_INITIAL: return "Initial";
1664: case ST_STARTING: return "Starting";
1665: case ST_CLOSED: return "Closed";
1666: case ST_STOPPED: return "Stopped";
1667: case ST_CLOSING: return "Closing";
1668: case ST_STOPPING: return "Stopping";
1669: case ST_REQSENT: return "Req-Sent";
1670: case ST_ACKRCVD: return "Ack-Rcvd";
1671: case ST_ACKSENT: return "Ack-Sent";
1672: case ST_OPENED: return "Opened";
1673: }
1674: return "???";
1675: }
1676:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>