xref: /freebsd/usr.sbin/ppp/fsm.c (revision 944f709824ad3bd24c8318843a65198f6ef36c85)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *		PPP Finite State Machine for LCP/IPCP
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan, Inc.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
20944f7098SBrian Somers  * $Id: fsm.c,v 1.15 1997/08/20 23:47:42 brian Exp $
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *  TODO:
23af57ed9fSAtsushi Murai  *		o Refer loglevel for log output
24af57ed9fSAtsushi Murai  *		o Better option log display
25af57ed9fSAtsushi Murai  */
26af57ed9fSAtsushi Murai #include "fsm.h"
27af57ed9fSAtsushi Murai #include "hdlc.h"
28af57ed9fSAtsushi Murai #include "lqr.h"
29af57ed9fSAtsushi Murai #include "lcpproto.h"
30af57ed9fSAtsushi Murai #include "lcp.h"
31ed6a16c1SPoul-Henning Kamp #include "ccp.h"
3271144dc5SBrian Somers #include "modem.h"
3371144dc5SBrian Somers #include "loadalias.h"
3471144dc5SBrian Somers #include "vars.h"
35af57ed9fSAtsushi Murai 
36af57ed9fSAtsushi Murai void FsmSendConfigReq(struct fsm * fp);
37af57ed9fSAtsushi Murai void FsmSendTerminateReq(struct fsm * fp);
38af57ed9fSAtsushi Murai void FsmInitRestartCounter(struct fsm * fp);
39af57ed9fSAtsushi Murai void FsmTimeout(struct fsm * fp);
40af57ed9fSAtsushi Murai 
41ed6a16c1SPoul-Henning Kamp char const *StateNames[] = {
42af57ed9fSAtsushi Murai   "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
43927145beSBrian Somers   "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
44af57ed9fSAtsushi Murai };
45af57ed9fSAtsushi Murai 
4671144dc5SBrian Somers static void
47944f7098SBrian Somers StoppedTimeout(struct fsm * fp)
4871144dc5SBrian Somers {
49cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Stopped timer expired\n");
5071144dc5SBrian Somers   if (modem != -1)
5171144dc5SBrian Somers     DownConnection();
5271144dc5SBrian Somers   else
5371144dc5SBrian Somers     FsmDown(fp);
5471144dc5SBrian Somers }
5571144dc5SBrian Somers 
56af57ed9fSAtsushi Murai void
57944f7098SBrian Somers FsmInit(struct fsm * fp)
58af57ed9fSAtsushi Murai {
59927145beSBrian Somers   LogPrintf(LogDEBUG, "FsmInit\n");
60af57ed9fSAtsushi Murai   fp->state = ST_INITIAL;
61af57ed9fSAtsushi Murai   fp->reqid = 1;
62af57ed9fSAtsushi Murai   fp->restart = 1;
63af57ed9fSAtsushi Murai   fp->maxconfig = 3;
64af57ed9fSAtsushi Murai }
65af57ed9fSAtsushi Murai 
66af57ed9fSAtsushi Murai void
67944f7098SBrian Somers NewState(struct fsm * fp, int new)
68af57ed9fSAtsushi Murai {
69cb611434SBrian Somers   LogPrintf(fp->LogLevel, "State change %s --> %s\n",
70927145beSBrian Somers 	    StateNames[fp->state], StateNames[new]);
71cb611434SBrian Somers   if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
72cb611434SBrian Somers     StopTimer(&fp->StoppedTimer);
73af57ed9fSAtsushi Murai   fp->state = new;
7471144dc5SBrian Somers   if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
75af57ed9fSAtsushi Murai     StopTimer(&fp->FsmTimer);
76cb611434SBrian Somers     if (new == ST_STOPPED && fp->StoppedTimer.load) {
77cb611434SBrian Somers       fp->StoppedTimer.state = TIMER_STOPPED;
78cb611434SBrian Somers       fp->StoppedTimer.func = StoppedTimeout;
79cb611434SBrian Somers       fp->StoppedTimer.arg = (void *) fp;
80cb611434SBrian Somers       StartTimer(&fp->StoppedTimer);
8171144dc5SBrian Somers     }
8271144dc5SBrian Somers   }
83af57ed9fSAtsushi Murai }
84af57ed9fSAtsushi Murai 
85af57ed9fSAtsushi Murai void
86944f7098SBrian Somers FsmOutput(struct fsm * fp, u_int code, u_int id, u_char * ptr, int count)
87af57ed9fSAtsushi Murai {
88af57ed9fSAtsushi Murai   int plen;
89af57ed9fSAtsushi Murai   struct fsmheader lh;
90af57ed9fSAtsushi Murai   struct mbuf *bp;
91af57ed9fSAtsushi Murai 
92af57ed9fSAtsushi Murai   plen = sizeof(struct fsmheader) + count;
93af57ed9fSAtsushi Murai   lh.code = code;
94af57ed9fSAtsushi Murai   lh.id = id;
95af57ed9fSAtsushi Murai   lh.length = htons(plen);
96af57ed9fSAtsushi Murai   bp = mballoc(plen, MB_FSM);
97af57ed9fSAtsushi Murai   bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader));
98af57ed9fSAtsushi Murai   if (count)
99af57ed9fSAtsushi Murai     bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count);
100927145beSBrian Somers   LogDumpBp(LogDEBUG, "FsmOutput", bp);
10176bd0c0aSDoug Rabson   HdlcOutput(PRI_LINK, fp->proto, bp);
102af57ed9fSAtsushi Murai }
103af57ed9fSAtsushi Murai 
104af57ed9fSAtsushi Murai void
105944f7098SBrian Somers FsmOpen(struct fsm * fp)
106af57ed9fSAtsushi Murai {
107af57ed9fSAtsushi Murai   switch (fp->state) {
108af57ed9fSAtsushi Murai     case ST_INITIAL:
109af57ed9fSAtsushi Murai     (fp->LayerStart) (fp);
110af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
111af57ed9fSAtsushi Murai     break;
112af57ed9fSAtsushi Murai   case ST_STARTING:
113af57ed9fSAtsushi Murai     break;
114af57ed9fSAtsushi Murai   case ST_CLOSED:
115af57ed9fSAtsushi Murai     if (fp->open_mode == OPEN_PASSIVE) {
116af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
117af57ed9fSAtsushi Murai     } else {
118af57ed9fSAtsushi Murai       FsmInitRestartCounter(fp);
119af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
120af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
121af57ed9fSAtsushi Murai     }
122af57ed9fSAtsushi Murai     break;
123af57ed9fSAtsushi Murai   case ST_STOPPED:		/* XXX: restart option */
124af57ed9fSAtsushi Murai   case ST_REQSENT:
125af57ed9fSAtsushi Murai   case ST_ACKRCVD:
126af57ed9fSAtsushi Murai   case ST_ACKSENT:
127af57ed9fSAtsushi Murai   case ST_OPENED:		/* XXX: restart option */
128af57ed9fSAtsushi Murai     break;
129af57ed9fSAtsushi Murai   case ST_CLOSING:		/* XXX: restart option */
130af57ed9fSAtsushi Murai   case ST_STOPPING:		/* XXX: restart option */
131af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPING);
132af57ed9fSAtsushi Murai     break;
133af57ed9fSAtsushi Murai   }
134af57ed9fSAtsushi Murai }
135af57ed9fSAtsushi Murai 
136af57ed9fSAtsushi Murai void
137944f7098SBrian Somers FsmUp(struct fsm * fp)
138af57ed9fSAtsushi Murai {
139af57ed9fSAtsushi Murai   switch (fp->state) {
140af57ed9fSAtsushi Murai     case ST_INITIAL:
141af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
142af57ed9fSAtsushi Murai     break;
143af57ed9fSAtsushi Murai   case ST_STARTING:
144af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
145af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
146af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
147af57ed9fSAtsushi Murai     break;
148af57ed9fSAtsushi Murai   default:
149cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]);
150af57ed9fSAtsushi Murai     break;
151af57ed9fSAtsushi Murai   }
152af57ed9fSAtsushi Murai }
153af57ed9fSAtsushi Murai 
154af57ed9fSAtsushi Murai void
155944f7098SBrian Somers FsmDown(struct fsm * fp)
156af57ed9fSAtsushi Murai {
157af57ed9fSAtsushi Murai   switch (fp->state) {
158af57ed9fSAtsushi Murai     case ST_CLOSED:
159af57ed9fSAtsushi Murai     case ST_CLOSING:
160af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
161af57ed9fSAtsushi Murai     break;
162af57ed9fSAtsushi Murai   case ST_STOPPED:
163af57ed9fSAtsushi Murai     (fp->LayerStart) (fp);
164af57ed9fSAtsushi Murai     /* Fall into.. */
165af57ed9fSAtsushi Murai   case ST_STOPPING:
166af57ed9fSAtsushi Murai   case ST_REQSENT:
167af57ed9fSAtsushi Murai   case ST_ACKRCVD:
168af57ed9fSAtsushi Murai   case ST_ACKSENT:
169af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
170af57ed9fSAtsushi Murai     break;
171af57ed9fSAtsushi Murai   case ST_OPENED:
172af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
173af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
174af57ed9fSAtsushi Murai     break;
175af57ed9fSAtsushi Murai   }
176af57ed9fSAtsushi Murai }
177af57ed9fSAtsushi Murai 
178af57ed9fSAtsushi Murai void
179944f7098SBrian Somers FsmClose(struct fsm * fp)
180af57ed9fSAtsushi Murai {
181af57ed9fSAtsushi Murai   switch (fp->state) {
182af57ed9fSAtsushi Murai     case ST_STARTING:
183af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
184af57ed9fSAtsushi Murai     break;
185af57ed9fSAtsushi Murai   case ST_STOPPED:
186af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
187af57ed9fSAtsushi Murai     break;
188af57ed9fSAtsushi Murai   case ST_STOPPING:
189af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
190af57ed9fSAtsushi Murai     break;
191af57ed9fSAtsushi Murai   case ST_OPENED:
192af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
193af57ed9fSAtsushi Murai     /* Fall down */
194af57ed9fSAtsushi Murai   case ST_REQSENT:
195af57ed9fSAtsushi Murai   case ST_ACKRCVD:
196af57ed9fSAtsushi Murai   case ST_ACKSENT:
197af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
198af57ed9fSAtsushi Murai     FsmSendTerminateReq(fp);
199af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
200af57ed9fSAtsushi Murai     break;
201af57ed9fSAtsushi Murai   }
202af57ed9fSAtsushi Murai }
203af57ed9fSAtsushi Murai 
204af57ed9fSAtsushi Murai /*
205af57ed9fSAtsushi Murai  *	Send functions
206af57ed9fSAtsushi Murai  */
207af57ed9fSAtsushi Murai void
208944f7098SBrian Somers FsmSendConfigReq(struct fsm * fp)
209af57ed9fSAtsushi Murai {
210af57ed9fSAtsushi Murai   if (--fp->maxconfig > 0) {
211af57ed9fSAtsushi Murai     (fp->SendConfigReq) (fp);
212af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);	/* Start restart timer */
213af57ed9fSAtsushi Murai     fp->restart--;		/* Decrement restart counter */
214af57ed9fSAtsushi Murai   } else {
215af57ed9fSAtsushi Murai     FsmClose(fp);
216af57ed9fSAtsushi Murai   }
217af57ed9fSAtsushi Murai }
218af57ed9fSAtsushi Murai 
219af57ed9fSAtsushi Murai void
220944f7098SBrian Somers FsmSendTerminateReq(struct fsm * fp)
221af57ed9fSAtsushi Murai {
222cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendTerminateReq.\n");
223af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
224af57ed9fSAtsushi Murai   (fp->SendTerminateReq) (fp);
225af57ed9fSAtsushi Murai   StartTimer(&fp->FsmTimer);	/* Start restart timer */
226af57ed9fSAtsushi Murai   fp->restart--;		/* Decrement restart counter */
227af57ed9fSAtsushi Murai }
228af57ed9fSAtsushi Murai 
229af57ed9fSAtsushi Murai static void
230944f7098SBrian Somers FsmSendConfigAck(struct fsm * fp,
231944f7098SBrian Somers 		 struct fsmheader * lhp,
232944f7098SBrian Somers 		 u_char * option,
233944f7098SBrian Somers 		 int count)
234af57ed9fSAtsushi Murai {
235cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]);
23653c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
237af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
238af57ed9fSAtsushi Murai }
239af57ed9fSAtsushi Murai 
240af57ed9fSAtsushi Murai static void
241944f7098SBrian Somers FsmSendConfigRej(struct fsm * fp,
242944f7098SBrian Somers 		 struct fsmheader * lhp,
243944f7098SBrian Somers 		 u_char * option,
244944f7098SBrian Somers 		 int count)
245af57ed9fSAtsushi Murai {
246cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]);
24753c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
248af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
249af57ed9fSAtsushi Murai }
250af57ed9fSAtsushi Murai 
251af57ed9fSAtsushi Murai static void
252944f7098SBrian Somers FsmSendConfigNak(struct fsm * fp,
253944f7098SBrian Somers 		 struct fsmheader * lhp,
254944f7098SBrian Somers 		 u_char * option,
255944f7098SBrian Somers 		 int count)
256af57ed9fSAtsushi Murai {
257cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]);
25853c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
259af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
260af57ed9fSAtsushi Murai }
261af57ed9fSAtsushi Murai 
262af57ed9fSAtsushi Murai /*
263af57ed9fSAtsushi Murai  *	Timeout actions
264af57ed9fSAtsushi Murai  */
265af57ed9fSAtsushi Murai void
266944f7098SBrian Somers FsmTimeout(struct fsm * fp)
267af57ed9fSAtsushi Murai {
268af57ed9fSAtsushi Murai   if (fp->restart) {
269af57ed9fSAtsushi Murai     switch (fp->state) {
270af57ed9fSAtsushi Murai       case ST_CLOSING:
271af57ed9fSAtsushi Murai       case ST_STOPPING:
272af57ed9fSAtsushi Murai       FsmSendTerminateReq(fp);
273af57ed9fSAtsushi Murai       break;
274af57ed9fSAtsushi Murai     case ST_REQSENT:
275af57ed9fSAtsushi Murai     case ST_ACKSENT:
276af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
277af57ed9fSAtsushi Murai       break;
278af57ed9fSAtsushi Murai     case ST_ACKRCVD:
279af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
280af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
281af57ed9fSAtsushi Murai       break;
282af57ed9fSAtsushi Murai     }
283af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);
284af57ed9fSAtsushi Murai   } else {
285af57ed9fSAtsushi Murai     switch (fp->state) {
286af57ed9fSAtsushi Murai     case ST_CLOSING:
287af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
288af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
289af57ed9fSAtsushi Murai       break;
290af57ed9fSAtsushi Murai     case ST_STOPPING:
291af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
292af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
293af57ed9fSAtsushi Murai       break;
294af57ed9fSAtsushi Murai     case ST_REQSENT:		/* XXX: 3p */
295af57ed9fSAtsushi Murai     case ST_ACKSENT:
296af57ed9fSAtsushi Murai     case ST_ACKRCVD:
297af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
298af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
299af57ed9fSAtsushi Murai       break;
300af57ed9fSAtsushi Murai     }
301af57ed9fSAtsushi Murai   }
302af57ed9fSAtsushi Murai }
303af57ed9fSAtsushi Murai 
304af57ed9fSAtsushi Murai void
305944f7098SBrian Somers FsmInitRestartCounter(struct fsm * fp)
306af57ed9fSAtsushi Murai {
307af57ed9fSAtsushi Murai   StopTimer(&fp->FsmTimer);
308af57ed9fSAtsushi Murai   fp->FsmTimer.state = TIMER_STOPPED;
309af57ed9fSAtsushi Murai   fp->FsmTimer.func = FsmTimeout;
310af57ed9fSAtsushi Murai   fp->FsmTimer.arg = (void *) fp;
311af57ed9fSAtsushi Murai   (fp->InitRestartCounter) (fp);
312af57ed9fSAtsushi Murai }
313af57ed9fSAtsushi Murai 
314af57ed9fSAtsushi Murai /*
315af57ed9fSAtsushi Murai  *   Actions when receive packets
316af57ed9fSAtsushi Murai  */
317af57ed9fSAtsushi Murai void
318944f7098SBrian Somers FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
319944f7098SBrian Somers /* RCR */
320af57ed9fSAtsushi Murai {
32153c9f6c0SAtsushi Murai   int plen, flen;
322af57ed9fSAtsushi Murai   int ackaction = 0;
323af57ed9fSAtsushi Murai 
324af57ed9fSAtsushi Murai   plen = plength(bp);
32553c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
32653c9f6c0SAtsushi Murai   if (plen < flen) {
327927145beSBrian Somers     LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)", plen, flen);
328af57ed9fSAtsushi Murai     pfree(bp);
329af57ed9fSAtsushi Murai     return;
330af57ed9fSAtsushi Murai   }
331af57ed9fSAtsushi Murai 
332af57ed9fSAtsushi Murai   /*
333af57ed9fSAtsushi Murai    * Check and process easy case
334af57ed9fSAtsushi Murai    */
335af57ed9fSAtsushi Murai   switch (fp->state) {
336af57ed9fSAtsushi Murai   case ST_INITIAL:
337af57ed9fSAtsushi Murai   case ST_STARTING:
338cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]);
339af57ed9fSAtsushi Murai     pfree(bp);
340af57ed9fSAtsushi Murai     return;
341af57ed9fSAtsushi Murai   case ST_CLOSED:
342af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
343af57ed9fSAtsushi Murai     pfree(bp);
344af57ed9fSAtsushi Murai     return;
345af57ed9fSAtsushi Murai   case ST_CLOSING:
346af57ed9fSAtsushi Murai   case ST_STOPPING:
347927145beSBrian Somers     LogPrintf(LogERROR, "Got ConfigReq while state = %d\n", fp->state);
348af57ed9fSAtsushi Murai     pfree(bp);
349af57ed9fSAtsushi Murai     return;
350af57ed9fSAtsushi Murai   }
351af57ed9fSAtsushi Murai 
35253c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REQ);
353af57ed9fSAtsushi Murai 
354af57ed9fSAtsushi Murai   if (nakp == NakBuff && rejp == RejBuff)
355af57ed9fSAtsushi Murai     ackaction = 1;
356af57ed9fSAtsushi Murai 
357af57ed9fSAtsushi Murai   switch (fp->state) {
358af57ed9fSAtsushi Murai   case ST_OPENED:
359af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
360af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
361af57ed9fSAtsushi Murai     break;
362af57ed9fSAtsushi Murai   case ST_STOPPED:
363af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
364af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
365af57ed9fSAtsushi Murai     break;
366af57ed9fSAtsushi Murai   }
367af57ed9fSAtsushi Murai 
368af57ed9fSAtsushi Murai   if (rejp != RejBuff)
369af57ed9fSAtsushi Murai     FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff);
370af57ed9fSAtsushi Murai   if (nakp != NakBuff)
371af57ed9fSAtsushi Murai     FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff);
372af57ed9fSAtsushi Murai   if (ackaction)
373af57ed9fSAtsushi Murai     FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff);
374af57ed9fSAtsushi Murai 
375af57ed9fSAtsushi Murai   switch (fp->state) {
376af57ed9fSAtsushi Murai   case ST_STOPPED:
377af57ed9fSAtsushi Murai   case ST_OPENED:
378af57ed9fSAtsushi Murai     if (ackaction)
379af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
380af57ed9fSAtsushi Murai     else
381af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
382af57ed9fSAtsushi Murai     break;
383af57ed9fSAtsushi Murai   case ST_REQSENT:
384af57ed9fSAtsushi Murai     if (ackaction)
385af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
386af57ed9fSAtsushi Murai     break;
387af57ed9fSAtsushi Murai   case ST_ACKRCVD:
388af57ed9fSAtsushi Murai     if (ackaction) {
389af57ed9fSAtsushi Murai       NewState(fp, ST_OPENED);
390af57ed9fSAtsushi Murai       (fp->LayerUp) (fp);
391af57ed9fSAtsushi Murai     }
392af57ed9fSAtsushi Murai     break;
393af57ed9fSAtsushi Murai   case ST_ACKSENT:
394af57ed9fSAtsushi Murai     if (!ackaction)
395af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
396af57ed9fSAtsushi Murai     break;
397af57ed9fSAtsushi Murai   }
398af57ed9fSAtsushi Murai   pfree(bp);
399af57ed9fSAtsushi Murai }
400af57ed9fSAtsushi Murai 
401af57ed9fSAtsushi Murai void
402944f7098SBrian Somers FsmRecvConfigAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
403944f7098SBrian Somers /* RCA */
404af57ed9fSAtsushi Murai {
405af57ed9fSAtsushi Murai   switch (fp->state) {
406af57ed9fSAtsushi Murai     case ST_CLOSED:
407af57ed9fSAtsushi Murai     case ST_STOPPED:
408af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
409af57ed9fSAtsushi Murai     break;
410af57ed9fSAtsushi Murai   case ST_CLOSING:
411af57ed9fSAtsushi Murai   case ST_STOPPING:
412af57ed9fSAtsushi Murai     break;
413af57ed9fSAtsushi Murai   case ST_REQSENT:
414af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
415af57ed9fSAtsushi Murai     NewState(fp, ST_ACKRCVD);
416af57ed9fSAtsushi Murai     break;
417af57ed9fSAtsushi Murai   case ST_ACKRCVD:
418af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
419af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
420af57ed9fSAtsushi Murai     break;
421af57ed9fSAtsushi Murai   case ST_ACKSENT:
422af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
423af57ed9fSAtsushi Murai     NewState(fp, ST_OPENED);
424af57ed9fSAtsushi Murai     (fp->LayerUp) (fp);
425af57ed9fSAtsushi Murai     break;
426af57ed9fSAtsushi Murai   case ST_OPENED:
427af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
428af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
429af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
430af57ed9fSAtsushi Murai     break;
431af57ed9fSAtsushi Murai   }
432af57ed9fSAtsushi Murai   pfree(bp);
433af57ed9fSAtsushi Murai }
434af57ed9fSAtsushi Murai 
435af57ed9fSAtsushi Murai void
436944f7098SBrian Somers FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
437944f7098SBrian Somers /* RCN */
438af57ed9fSAtsushi Murai {
43953c9f6c0SAtsushi Murai   int plen, flen;
440af57ed9fSAtsushi Murai 
441af57ed9fSAtsushi Murai   plen = plength(bp);
44253c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
44353c9f6c0SAtsushi Murai   if (plen < flen) {
444af57ed9fSAtsushi Murai     pfree(bp);
445af57ed9fSAtsushi Murai     return;
446af57ed9fSAtsushi Murai   }
447af57ed9fSAtsushi Murai 
448af57ed9fSAtsushi Murai   /*
449af57ed9fSAtsushi Murai    * Check and process easy case
450af57ed9fSAtsushi Murai    */
451af57ed9fSAtsushi Murai   switch (fp->state) {
452af57ed9fSAtsushi Murai   case ST_INITIAL:
453af57ed9fSAtsushi Murai   case ST_STARTING:
454cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", StateNames[fp->state]);
455af57ed9fSAtsushi Murai     pfree(bp);
456af57ed9fSAtsushi Murai     return;
457af57ed9fSAtsushi Murai   case ST_CLOSED:
458af57ed9fSAtsushi Murai   case ST_STOPPED:
459af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
460af57ed9fSAtsushi Murai     pfree(bp);
461af57ed9fSAtsushi Murai     return;
462af57ed9fSAtsushi Murai   case ST_CLOSING:
463af57ed9fSAtsushi Murai   case ST_STOPPING:
464af57ed9fSAtsushi Murai     pfree(bp);
465af57ed9fSAtsushi Murai     return;
466af57ed9fSAtsushi Murai   }
467af57ed9fSAtsushi Murai 
46853c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_NAK);
469af57ed9fSAtsushi Murai 
470af57ed9fSAtsushi Murai   switch (fp->state) {
471af57ed9fSAtsushi Murai   case ST_REQSENT:
472af57ed9fSAtsushi Murai   case ST_ACKSENT:
473af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
474af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
475af57ed9fSAtsushi Murai     break;
476af57ed9fSAtsushi Murai   case ST_OPENED:
477af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
478af57ed9fSAtsushi Murai     /* Fall down */
479af57ed9fSAtsushi Murai   case ST_ACKRCVD:
480af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
481af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
482af57ed9fSAtsushi Murai     break;
483af57ed9fSAtsushi Murai   }
484af57ed9fSAtsushi Murai 
485af57ed9fSAtsushi Murai   pfree(bp);
486af57ed9fSAtsushi Murai }
487af57ed9fSAtsushi Murai 
488af57ed9fSAtsushi Murai void
489944f7098SBrian Somers FsmRecvTermReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
490944f7098SBrian Somers /* RTR */
491af57ed9fSAtsushi Murai {
492af57ed9fSAtsushi Murai   switch (fp->state) {
493af57ed9fSAtsushi Murai     case ST_INITIAL:
494af57ed9fSAtsushi Murai     case ST_STARTING:
495cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", StateNames[fp->state]);
496af57ed9fSAtsushi Murai     break;
497af57ed9fSAtsushi Murai   case ST_CLOSED:
498af57ed9fSAtsushi Murai   case ST_STOPPED:
499af57ed9fSAtsushi Murai   case ST_CLOSING:
500af57ed9fSAtsushi Murai   case ST_STOPPING:
501af57ed9fSAtsushi Murai   case ST_REQSENT:
502af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
503af57ed9fSAtsushi Murai     break;
504af57ed9fSAtsushi Murai   case ST_ACKRCVD:
505af57ed9fSAtsushi Murai   case ST_ACKSENT:
506af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
507af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
508af57ed9fSAtsushi Murai     break;
509af57ed9fSAtsushi Murai   case ST_OPENED:
5108f2fa0eeSBrian Somers     (fp->LayerDown) (fp);
511af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
5128f2fa0eeSBrian Somers     StartTimer(&fp->FsmTimer);	/* Start restart timer */
5138f2fa0eeSBrian Somers     fp->restart = 0;
5148f2fa0eeSBrian Somers     NewState(fp, ST_STOPPING);
515af57ed9fSAtsushi Murai     break;
516af57ed9fSAtsushi Murai   }
517af57ed9fSAtsushi Murai   pfree(bp);
518af57ed9fSAtsushi Murai }
519af57ed9fSAtsushi Murai 
520af57ed9fSAtsushi Murai void
521944f7098SBrian Somers FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
522944f7098SBrian Somers /* RTA */
523af57ed9fSAtsushi Murai {
524af57ed9fSAtsushi Murai   switch (fp->state) {
525af57ed9fSAtsushi Murai     case ST_CLOSING:
526af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
527af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
528af57ed9fSAtsushi Murai     break;
529af57ed9fSAtsushi Murai   case ST_STOPPING:
530af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPED);
531af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
532af57ed9fSAtsushi Murai     break;
533af57ed9fSAtsushi Murai   case ST_ACKRCVD:
534af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
535af57ed9fSAtsushi Murai     break;
536af57ed9fSAtsushi Murai   case ST_OPENED:
537af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
538af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
539af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
540af57ed9fSAtsushi Murai     break;
541af57ed9fSAtsushi Murai   }
542af57ed9fSAtsushi Murai   pfree(bp);
543af57ed9fSAtsushi Murai }
544af57ed9fSAtsushi Murai 
545af57ed9fSAtsushi Murai void
546944f7098SBrian Somers FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
547944f7098SBrian Somers /* RCJ */
548af57ed9fSAtsushi Murai {
54953c9f6c0SAtsushi Murai   int plen, flen;
550af57ed9fSAtsushi Murai 
551af57ed9fSAtsushi Murai   plen = plength(bp);
55253c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
55353c9f6c0SAtsushi Murai   if (plen < flen) {
554af57ed9fSAtsushi Murai     pfree(bp);
555af57ed9fSAtsushi Murai     return;
556af57ed9fSAtsushi Murai   }
557cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvConfigRej.\n");
558af57ed9fSAtsushi Murai 
559af57ed9fSAtsushi Murai   /*
560af57ed9fSAtsushi Murai    * Check and process easy case
561af57ed9fSAtsushi Murai    */
562af57ed9fSAtsushi Murai   switch (fp->state) {
563af57ed9fSAtsushi Murai   case ST_INITIAL:
564af57ed9fSAtsushi Murai   case ST_STARTING:
565cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", StateNames[fp->state]);
566af57ed9fSAtsushi Murai     pfree(bp);
567af57ed9fSAtsushi Murai     return;
568af57ed9fSAtsushi Murai   case ST_CLOSED:
569af57ed9fSAtsushi Murai   case ST_STOPPED:
570af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
571af57ed9fSAtsushi Murai     pfree(bp);
572af57ed9fSAtsushi Murai     return;
573af57ed9fSAtsushi Murai   case ST_CLOSING:
574af57ed9fSAtsushi Murai   case ST_STOPPING:
575af57ed9fSAtsushi Murai     pfree(bp);
576af57ed9fSAtsushi Murai     return;
577af57ed9fSAtsushi Murai   }
578af57ed9fSAtsushi Murai 
57953c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REJ);
580af57ed9fSAtsushi Murai 
581af57ed9fSAtsushi Murai   switch (fp->state) {
582af57ed9fSAtsushi Murai   case ST_REQSENT:
583af57ed9fSAtsushi Murai   case ST_ACKSENT:
584af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
585af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
586af57ed9fSAtsushi Murai     break;
587af57ed9fSAtsushi Murai   case ST_OPENED:
588af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
589af57ed9fSAtsushi Murai     /* Fall down */
590af57ed9fSAtsushi Murai   case ST_ACKRCVD:
591af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
592af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
593af57ed9fSAtsushi Murai     break;
594af57ed9fSAtsushi Murai   }
595af57ed9fSAtsushi Murai   pfree(bp);
596af57ed9fSAtsushi Murai }
597af57ed9fSAtsushi Murai 
598af57ed9fSAtsushi Murai void
599944f7098SBrian Somers FsmRecvCodeRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
600af57ed9fSAtsushi Murai {
601cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvCodeRej\n");
602af57ed9fSAtsushi Murai   pfree(bp);
603af57ed9fSAtsushi Murai }
604af57ed9fSAtsushi Murai 
605af57ed9fSAtsushi Murai void
606944f7098SBrian Somers FsmRecvProtoRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
607af57ed9fSAtsushi Murai {
608af57ed9fSAtsushi Murai   u_short *sp, proto;
609af57ed9fSAtsushi Murai 
610af57ed9fSAtsushi Murai   sp = (u_short *) MBUF_CTOP(bp);
611af57ed9fSAtsushi Murai   proto = ntohs(*sp);
612cb611434SBrian Somers   LogPrintf(fp->LogLevel, "-- Protocol (%04x) was rejected.\n", proto);
613af57ed9fSAtsushi Murai 
614af57ed9fSAtsushi Murai   switch (proto) {
615af57ed9fSAtsushi Murai   case PROTO_LQR:
616af57ed9fSAtsushi Murai     StopLqr(LQM_LQR);
617af57ed9fSAtsushi Murai     break;
618af57ed9fSAtsushi Murai   case PROTO_CCP:
619af57ed9fSAtsushi Murai     fp = &CcpFsm;
620af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
621af57ed9fSAtsushi Murai     switch (fp->state) {
622af57ed9fSAtsushi Murai     case ST_CLOSED:
623af57ed9fSAtsushi Murai     case ST_CLOSING:
624af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
625af57ed9fSAtsushi Murai     default:
626af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
627af57ed9fSAtsushi Murai       break;
628af57ed9fSAtsushi Murai     }
629af57ed9fSAtsushi Murai     break;
630af57ed9fSAtsushi Murai   }
631af57ed9fSAtsushi Murai   pfree(bp);
632af57ed9fSAtsushi Murai }
633af57ed9fSAtsushi Murai 
634af57ed9fSAtsushi Murai void
635944f7098SBrian Somers FsmRecvEchoReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
636af57ed9fSAtsushi Murai {
637af57ed9fSAtsushi Murai   u_char *cp;
638af57ed9fSAtsushi Murai   u_long *lp, magic;
639af57ed9fSAtsushi Murai 
640af57ed9fSAtsushi Murai   cp = MBUF_CTOP(bp);
641af57ed9fSAtsushi Murai   lp = (u_long *) cp;
642af57ed9fSAtsushi Murai   magic = ntohl(*lp);
643af57ed9fSAtsushi Murai   if (magic != LcpInfo.his_magic) {
644927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n");
645af57ed9fSAtsushi Murai     /* XXX: We should send terminate request */
646af57ed9fSAtsushi Murai   }
647af57ed9fSAtsushi Murai   if (fp->state == ST_OPENED) {
648af57ed9fSAtsushi Murai     *lp = htonl(LcpInfo.want_magic);	/* Insert local magic number */
649cb611434SBrian Somers     LogPrintf(fp->LogLevel, "SendEchoRep(%s)\n", StateNames[fp->state]);
650af57ed9fSAtsushi Murai     FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp));
651af57ed9fSAtsushi Murai   }
652af57ed9fSAtsushi Murai   pfree(bp);
653af57ed9fSAtsushi Murai }
654af57ed9fSAtsushi Murai 
655af57ed9fSAtsushi Murai void
656944f7098SBrian Somers FsmRecvEchoRep(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
657af57ed9fSAtsushi Murai {
658af57ed9fSAtsushi Murai   u_long *lp, magic;
659af57ed9fSAtsushi Murai 
660af57ed9fSAtsushi Murai   lp = (u_long *) MBUF_CTOP(bp);
661af57ed9fSAtsushi Murai   magic = ntohl(*lp);
66285c59f05SJoerg Wunsch /*
66385c59f05SJoerg Wunsch  * Tolerate echo replies with either magic number
66485c59f05SJoerg Wunsch  */
66585c59f05SJoerg Wunsch   if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) {
666927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n",
667af57ed9fSAtsushi Murai 	      LcpInfo.his_magic, magic);
668944f7098SBrian Somers 
669af57ed9fSAtsushi Murai     /*
670944f7098SBrian Somers      * XXX: We should send terminate request. But poor implementation may die
671944f7098SBrian Somers      * as a result.
672af57ed9fSAtsushi Murai      */
673af57ed9fSAtsushi Murai   }
674af57ed9fSAtsushi Murai   RecvEchoLqr(bp);
675af57ed9fSAtsushi Murai   pfree(bp);
676af57ed9fSAtsushi Murai }
677af57ed9fSAtsushi Murai 
678af57ed9fSAtsushi Murai void
679944f7098SBrian Somers FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
680af57ed9fSAtsushi Murai {
681cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvDiscReq\n");
682af57ed9fSAtsushi Murai   pfree(bp);
683af57ed9fSAtsushi Murai }
684af57ed9fSAtsushi Murai 
685af57ed9fSAtsushi Murai void
686944f7098SBrian Somers FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
687af57ed9fSAtsushi Murai {
688cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvIdent\n");
689af57ed9fSAtsushi Murai   pfree(bp);
690af57ed9fSAtsushi Murai }
691af57ed9fSAtsushi Murai 
692af57ed9fSAtsushi Murai void
693944f7098SBrian Somers FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
694af57ed9fSAtsushi Murai {
695cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvTimeRemain\n");
696af57ed9fSAtsushi Murai   pfree(bp);
697af57ed9fSAtsushi Murai }
698af57ed9fSAtsushi Murai 
699af57ed9fSAtsushi Murai void
700944f7098SBrian Somers FsmRecvResetReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
701af57ed9fSAtsushi Murai {
702cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetReq\n");
703af57ed9fSAtsushi Murai   CcpRecvResetReq(fp);
704cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendResetAck\n");
705af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0);
706af57ed9fSAtsushi Murai   pfree(bp);
707af57ed9fSAtsushi Murai }
708af57ed9fSAtsushi Murai 
709af57ed9fSAtsushi Murai void
710944f7098SBrian Somers FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
711af57ed9fSAtsushi Murai {
712cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetAck\n");
713af57ed9fSAtsushi Murai   fp->reqid++;
714af57ed9fSAtsushi Murai   pfree(bp);
715af57ed9fSAtsushi Murai }
716af57ed9fSAtsushi Murai 
717af57ed9fSAtsushi Murai struct fsmcodedesc FsmCodes[] = {
718af57ed9fSAtsushi Murai   {FsmRecvConfigReq, "Configure Request",},
719af57ed9fSAtsushi Murai   {FsmRecvConfigAck, "Configure Ack",},
720af57ed9fSAtsushi Murai   {FsmRecvConfigNak, "Configure Nak",},
721af57ed9fSAtsushi Murai   {FsmRecvConfigRej, "Configure Reject",},
722af57ed9fSAtsushi Murai   {FsmRecvTermReq, "Terminate Request",},
723af57ed9fSAtsushi Murai   {FsmRecvTermAck, "Terminate Ack",},
724af57ed9fSAtsushi Murai   {FsmRecvCodeRej, "Code Reject",},
725af57ed9fSAtsushi Murai   {FsmRecvProtoRej, "Protocol Reject",},
726af57ed9fSAtsushi Murai   {FsmRecvEchoReq, "Echo Request",},
727af57ed9fSAtsushi Murai   {FsmRecvEchoRep, "Echo Reply",},
728af57ed9fSAtsushi Murai   {FsmRecvDiscReq, "Discard Request",},
729af57ed9fSAtsushi Murai   {FsmRecvIdent, "Ident",},
730af57ed9fSAtsushi Murai   {FsmRecvTimeRemain, "Time Remain",},
731af57ed9fSAtsushi Murai   {FsmRecvResetReq, "Reset Request",},
732af57ed9fSAtsushi Murai   {FsmRecvResetAck, "Reset Ack",},
733af57ed9fSAtsushi Murai };
734af57ed9fSAtsushi Murai 
735af57ed9fSAtsushi Murai void
736944f7098SBrian Somers FsmInput(struct fsm * fp, struct mbuf * bp)
737af57ed9fSAtsushi Murai {
738af57ed9fSAtsushi Murai   int len;
739af57ed9fSAtsushi Murai   struct fsmheader *lhp;
740af57ed9fSAtsushi Murai   struct fsmcodedesc *codep;
741af57ed9fSAtsushi Murai 
742af57ed9fSAtsushi Murai   len = plength(bp);
743af57ed9fSAtsushi Murai   if (len < sizeof(struct fsmheader)) {
744af57ed9fSAtsushi Murai     pfree(bp);
745af57ed9fSAtsushi Murai     return;
746af57ed9fSAtsushi Murai   }
747af57ed9fSAtsushi Murai   lhp = (struct fsmheader *) MBUF_CTOP(bp);
748af57ed9fSAtsushi Murai   if (lhp->code == 0 || lhp->code > fp->max_code) {
749af57ed9fSAtsushi Murai     pfree(bp);			/* XXX: Should send code reject */
750af57ed9fSAtsushi Murai     return;
751af57ed9fSAtsushi Murai   }
752af57ed9fSAtsushi Murai   bp->offset += sizeof(struct fsmheader);
753af57ed9fSAtsushi Murai   bp->cnt -= sizeof(struct fsmheader);
754af57ed9fSAtsushi Murai 
755af57ed9fSAtsushi Murai   codep = FsmCodes + lhp->code - 1;
756cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n",
757927145beSBrian Somers 	    codep->name, lhp->id, StateNames[fp->state], fp->state);
758927145beSBrian Somers   if (LogIsKept(LogDEBUG))
759af57ed9fSAtsushi Murai     LogMemory();
760af57ed9fSAtsushi Murai   (codep->action) (fp, lhp, bp);
761927145beSBrian Somers   if (LogIsKept(LogDEBUG))
762af57ed9fSAtsushi Murai     LogMemory();
763af57ed9fSAtsushi Murai }
764