xref: /freebsd/usr.sbin/ppp/fsm.c (revision 75240ed1789e0754da5b1024dcb80dcfc5dae0c3)
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  *
2075240ed1SBrian Somers  * $Id: fsm.c,v 1.19 1997/09/10 23:55:35 brian Exp $
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *  TODO:
23af57ed9fSAtsushi Murai  *		o Refer loglevel for log output
24af57ed9fSAtsushi Murai  *		o Better option log display
25af57ed9fSAtsushi Murai  */
2675240ed1SBrian Somers #include <sys/param.h>
2775240ed1SBrian Somers #include <netinet/in.h>
2875240ed1SBrian Somers 
2975240ed1SBrian Somers #include <stdio.h>
3075240ed1SBrian Somers #include <string.h>
3175240ed1SBrian Somers #include <termios.h>
3275240ed1SBrian Somers 
3375240ed1SBrian Somers #include "mbuf.h"
3475240ed1SBrian Somers #include "log.h"
3575240ed1SBrian Somers #include "defs.h"
3675240ed1SBrian Somers #include "timer.h"
37af57ed9fSAtsushi Murai #include "fsm.h"
38af57ed9fSAtsushi Murai #include "hdlc.h"
39af57ed9fSAtsushi Murai #include "lqr.h"
40af57ed9fSAtsushi Murai #include "lcpproto.h"
41af57ed9fSAtsushi Murai #include "lcp.h"
42ed6a16c1SPoul-Henning Kamp #include "ccp.h"
4371144dc5SBrian Somers #include "modem.h"
4471144dc5SBrian Somers #include "loadalias.h"
4575240ed1SBrian Somers #include "command.h"
4671144dc5SBrian Somers #include "vars.h"
47b0f5f9edSBrian Somers #include "pred.h"
48af57ed9fSAtsushi Murai 
4975240ed1SBrian Somers u_char AckBuff[200];
5075240ed1SBrian Somers u_char NakBuff[200];
5175240ed1SBrian Somers u_char RejBuff[100];
5275240ed1SBrian Somers u_char ReqBuff[200];
5375240ed1SBrian Somers u_char *ackp = NULL;
5475240ed1SBrian Somers u_char *nakp = NULL;
5575240ed1SBrian Somers u_char *rejp = NULL;
5675240ed1SBrian Somers 
5775240ed1SBrian Somers static void FsmSendConfigReq(struct fsm *);
5875240ed1SBrian Somers static void FsmSendTerminateReq(struct fsm *);
5975240ed1SBrian Somers static void FsmInitRestartCounter(struct fsm *);
60af57ed9fSAtsushi Murai 
61ed6a16c1SPoul-Henning Kamp char const *StateNames[] = {
62af57ed9fSAtsushi Murai   "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
63927145beSBrian Somers   "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
64af57ed9fSAtsushi Murai };
65af57ed9fSAtsushi Murai 
6671144dc5SBrian Somers static void
67944f7098SBrian Somers StoppedTimeout(struct fsm * fp)
6871144dc5SBrian Somers {
69cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Stopped timer expired\n");
7071144dc5SBrian Somers   if (modem != -1)
7171144dc5SBrian Somers     DownConnection();
7271144dc5SBrian Somers   else
7371144dc5SBrian Somers     FsmDown(fp);
7471144dc5SBrian Somers }
7571144dc5SBrian Somers 
76af57ed9fSAtsushi Murai void
77944f7098SBrian Somers FsmInit(struct fsm * fp)
78af57ed9fSAtsushi Murai {
79927145beSBrian Somers   LogPrintf(LogDEBUG, "FsmInit\n");
80af57ed9fSAtsushi Murai   fp->state = ST_INITIAL;
81af57ed9fSAtsushi Murai   fp->reqid = 1;
82af57ed9fSAtsushi Murai   fp->restart = 1;
83af57ed9fSAtsushi Murai   fp->maxconfig = 3;
84af57ed9fSAtsushi Murai }
85af57ed9fSAtsushi Murai 
8675240ed1SBrian Somers static void
87944f7098SBrian Somers NewState(struct fsm * fp, int new)
88af57ed9fSAtsushi Murai {
89cb611434SBrian Somers   LogPrintf(fp->LogLevel, "State change %s --> %s\n",
90927145beSBrian Somers 	    StateNames[fp->state], StateNames[new]);
91cb611434SBrian Somers   if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
92cb611434SBrian Somers     StopTimer(&fp->StoppedTimer);
93af57ed9fSAtsushi Murai   fp->state = new;
9471144dc5SBrian Somers   if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
95af57ed9fSAtsushi Murai     StopTimer(&fp->FsmTimer);
96cb611434SBrian Somers     if (new == ST_STOPPED && fp->StoppedTimer.load) {
97cb611434SBrian Somers       fp->StoppedTimer.state = TIMER_STOPPED;
98cb611434SBrian Somers       fp->StoppedTimer.func = StoppedTimeout;
99cb611434SBrian Somers       fp->StoppedTimer.arg = (void *) fp;
100cb611434SBrian Somers       StartTimer(&fp->StoppedTimer);
10171144dc5SBrian Somers     }
10271144dc5SBrian Somers   }
103af57ed9fSAtsushi Murai }
104af57ed9fSAtsushi Murai 
105af57ed9fSAtsushi Murai void
106944f7098SBrian Somers FsmOutput(struct fsm * fp, u_int code, u_int id, u_char * ptr, int count)
107af57ed9fSAtsushi Murai {
108af57ed9fSAtsushi Murai   int plen;
109af57ed9fSAtsushi Murai   struct fsmheader lh;
110af57ed9fSAtsushi Murai   struct mbuf *bp;
111af57ed9fSAtsushi Murai 
112af57ed9fSAtsushi Murai   plen = sizeof(struct fsmheader) + count;
113af57ed9fSAtsushi Murai   lh.code = code;
114af57ed9fSAtsushi Murai   lh.id = id;
115af57ed9fSAtsushi Murai   lh.length = htons(plen);
116af57ed9fSAtsushi Murai   bp = mballoc(plen, MB_FSM);
11775240ed1SBrian Somers   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
118af57ed9fSAtsushi Murai   if (count)
11975240ed1SBrian Somers     memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
120927145beSBrian Somers   LogDumpBp(LogDEBUG, "FsmOutput", bp);
12176bd0c0aSDoug Rabson   HdlcOutput(PRI_LINK, fp->proto, bp);
122af57ed9fSAtsushi Murai }
123af57ed9fSAtsushi Murai 
124af57ed9fSAtsushi Murai void
125944f7098SBrian Somers FsmOpen(struct fsm * fp)
126af57ed9fSAtsushi Murai {
127af57ed9fSAtsushi Murai   switch (fp->state) {
128af57ed9fSAtsushi Murai     case ST_INITIAL:
129af57ed9fSAtsushi Murai     (fp->LayerStart) (fp);
130af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
131af57ed9fSAtsushi Murai     break;
132af57ed9fSAtsushi Murai   case ST_STARTING:
133af57ed9fSAtsushi Murai     break;
134af57ed9fSAtsushi Murai   case ST_CLOSED:
135af57ed9fSAtsushi Murai     if (fp->open_mode == OPEN_PASSIVE) {
136af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
137af57ed9fSAtsushi Murai     } else {
138af57ed9fSAtsushi Murai       FsmInitRestartCounter(fp);
139af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
140af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
141af57ed9fSAtsushi Murai     }
142af57ed9fSAtsushi Murai     break;
143af57ed9fSAtsushi Murai   case ST_STOPPED:		/* XXX: restart option */
144af57ed9fSAtsushi Murai   case ST_REQSENT:
145af57ed9fSAtsushi Murai   case ST_ACKRCVD:
146af57ed9fSAtsushi Murai   case ST_ACKSENT:
147af57ed9fSAtsushi Murai   case ST_OPENED:		/* XXX: restart option */
148af57ed9fSAtsushi Murai     break;
149af57ed9fSAtsushi Murai   case ST_CLOSING:		/* XXX: restart option */
150af57ed9fSAtsushi Murai   case ST_STOPPING:		/* XXX: restart option */
151af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPING);
152af57ed9fSAtsushi Murai     break;
153af57ed9fSAtsushi Murai   }
154af57ed9fSAtsushi Murai }
155af57ed9fSAtsushi Murai 
156af57ed9fSAtsushi Murai void
157944f7098SBrian Somers FsmUp(struct fsm * fp)
158af57ed9fSAtsushi Murai {
159af57ed9fSAtsushi Murai   switch (fp->state) {
160af57ed9fSAtsushi Murai     case ST_INITIAL:
161af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
162af57ed9fSAtsushi Murai     break;
163af57ed9fSAtsushi Murai   case ST_STARTING:
164af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
165af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
166af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
167af57ed9fSAtsushi Murai     break;
168af57ed9fSAtsushi Murai   default:
169cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]);
170af57ed9fSAtsushi Murai     break;
171af57ed9fSAtsushi Murai   }
172af57ed9fSAtsushi Murai }
173af57ed9fSAtsushi Murai 
174af57ed9fSAtsushi Murai void
175944f7098SBrian Somers FsmDown(struct fsm * fp)
176af57ed9fSAtsushi Murai {
177af57ed9fSAtsushi Murai   switch (fp->state) {
178af57ed9fSAtsushi Murai     case ST_CLOSED:
179af57ed9fSAtsushi Murai     case ST_CLOSING:
180af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
181af57ed9fSAtsushi Murai     break;
182af57ed9fSAtsushi Murai   case ST_STOPPED:
183af57ed9fSAtsushi Murai     (fp->LayerStart) (fp);
184af57ed9fSAtsushi Murai     /* Fall into.. */
185af57ed9fSAtsushi Murai   case ST_STOPPING:
186af57ed9fSAtsushi Murai   case ST_REQSENT:
187af57ed9fSAtsushi Murai   case ST_ACKRCVD:
188af57ed9fSAtsushi Murai   case ST_ACKSENT:
189af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
190af57ed9fSAtsushi Murai     break;
191af57ed9fSAtsushi Murai   case ST_OPENED:
192af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
193af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
194af57ed9fSAtsushi Murai     break;
195af57ed9fSAtsushi Murai   }
196af57ed9fSAtsushi Murai }
197af57ed9fSAtsushi Murai 
198af57ed9fSAtsushi Murai void
199944f7098SBrian Somers FsmClose(struct fsm * fp)
200af57ed9fSAtsushi Murai {
201af57ed9fSAtsushi Murai   switch (fp->state) {
202af57ed9fSAtsushi Murai     case ST_STARTING:
203af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
204af57ed9fSAtsushi Murai     break;
205af57ed9fSAtsushi Murai   case ST_STOPPED:
206af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
207af57ed9fSAtsushi Murai     break;
208af57ed9fSAtsushi Murai   case ST_STOPPING:
209af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
210af57ed9fSAtsushi Murai     break;
211af57ed9fSAtsushi Murai   case ST_OPENED:
212af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
213af57ed9fSAtsushi Murai     /* Fall down */
214af57ed9fSAtsushi Murai   case ST_REQSENT:
215af57ed9fSAtsushi Murai   case ST_ACKRCVD:
216af57ed9fSAtsushi Murai   case ST_ACKSENT:
217af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
218af57ed9fSAtsushi Murai     FsmSendTerminateReq(fp);
219af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
220af57ed9fSAtsushi Murai     break;
221af57ed9fSAtsushi Murai   }
222af57ed9fSAtsushi Murai }
223af57ed9fSAtsushi Murai 
224af57ed9fSAtsushi Murai /*
225af57ed9fSAtsushi Murai  *	Send functions
226af57ed9fSAtsushi Murai  */
22775240ed1SBrian Somers static void
228944f7098SBrian Somers FsmSendConfigReq(struct fsm * fp)
229af57ed9fSAtsushi Murai {
230af57ed9fSAtsushi Murai   if (--fp->maxconfig > 0) {
231af57ed9fSAtsushi Murai     (fp->SendConfigReq) (fp);
232af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);	/* Start restart timer */
233af57ed9fSAtsushi Murai     fp->restart--;		/* Decrement restart counter */
234af57ed9fSAtsushi Murai   } else {
235af57ed9fSAtsushi Murai     FsmClose(fp);
236af57ed9fSAtsushi Murai   }
237af57ed9fSAtsushi Murai }
238af57ed9fSAtsushi Murai 
23975240ed1SBrian Somers static void
240944f7098SBrian Somers FsmSendTerminateReq(struct fsm * fp)
241af57ed9fSAtsushi Murai {
242cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendTerminateReq.\n");
243af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
244af57ed9fSAtsushi Murai   (fp->SendTerminateReq) (fp);
245af57ed9fSAtsushi Murai   StartTimer(&fp->FsmTimer);	/* Start restart timer */
246af57ed9fSAtsushi Murai   fp->restart--;		/* Decrement restart counter */
247af57ed9fSAtsushi Murai }
248af57ed9fSAtsushi Murai 
249af57ed9fSAtsushi Murai static void
250944f7098SBrian Somers FsmSendConfigAck(struct fsm * fp,
251944f7098SBrian Somers 		 struct fsmheader * lhp,
252944f7098SBrian Somers 		 u_char * option,
253944f7098SBrian Somers 		 int count)
254af57ed9fSAtsushi Murai {
255cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]);
25653c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
257af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
258af57ed9fSAtsushi Murai }
259af57ed9fSAtsushi Murai 
260af57ed9fSAtsushi Murai static void
261944f7098SBrian Somers FsmSendConfigRej(struct fsm * fp,
262944f7098SBrian Somers 		 struct fsmheader * lhp,
263944f7098SBrian Somers 		 u_char * option,
264944f7098SBrian Somers 		 int count)
265af57ed9fSAtsushi Murai {
266cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]);
26753c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
268af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
269af57ed9fSAtsushi Murai }
270af57ed9fSAtsushi Murai 
271af57ed9fSAtsushi Murai static void
272944f7098SBrian Somers FsmSendConfigNak(struct fsm * fp,
273944f7098SBrian Somers 		 struct fsmheader * lhp,
274944f7098SBrian Somers 		 u_char * option,
275944f7098SBrian Somers 		 int count)
276af57ed9fSAtsushi Murai {
277cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]);
27853c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
279af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
280af57ed9fSAtsushi Murai }
281af57ed9fSAtsushi Murai 
282af57ed9fSAtsushi Murai /*
283af57ed9fSAtsushi Murai  *	Timeout actions
284af57ed9fSAtsushi Murai  */
28575240ed1SBrian Somers static void
286944f7098SBrian Somers FsmTimeout(struct fsm * fp)
287af57ed9fSAtsushi Murai {
288af57ed9fSAtsushi Murai   if (fp->restart) {
289af57ed9fSAtsushi Murai     switch (fp->state) {
290af57ed9fSAtsushi Murai       case ST_CLOSING:
291af57ed9fSAtsushi Murai       case ST_STOPPING:
292af57ed9fSAtsushi Murai       FsmSendTerminateReq(fp);
293af57ed9fSAtsushi Murai       break;
294af57ed9fSAtsushi Murai     case ST_REQSENT:
295af57ed9fSAtsushi Murai     case ST_ACKSENT:
296af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
297af57ed9fSAtsushi Murai       break;
298af57ed9fSAtsushi Murai     case ST_ACKRCVD:
299af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
300af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
301af57ed9fSAtsushi Murai       break;
302af57ed9fSAtsushi Murai     }
303af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);
304af57ed9fSAtsushi Murai   } else {
305af57ed9fSAtsushi Murai     switch (fp->state) {
306af57ed9fSAtsushi Murai     case ST_CLOSING:
307af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
308af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
309af57ed9fSAtsushi Murai       break;
310af57ed9fSAtsushi Murai     case ST_STOPPING:
311af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
312af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
313af57ed9fSAtsushi Murai       break;
314af57ed9fSAtsushi Murai     case ST_REQSENT:		/* XXX: 3p */
315af57ed9fSAtsushi Murai     case ST_ACKSENT:
316af57ed9fSAtsushi Murai     case ST_ACKRCVD:
317af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
318af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
319af57ed9fSAtsushi Murai       break;
320af57ed9fSAtsushi Murai     }
321af57ed9fSAtsushi Murai   }
322af57ed9fSAtsushi Murai }
323af57ed9fSAtsushi Murai 
32475240ed1SBrian Somers static void
325944f7098SBrian Somers FsmInitRestartCounter(struct fsm * fp)
326af57ed9fSAtsushi Murai {
327af57ed9fSAtsushi Murai   StopTimer(&fp->FsmTimer);
328af57ed9fSAtsushi Murai   fp->FsmTimer.state = TIMER_STOPPED;
329af57ed9fSAtsushi Murai   fp->FsmTimer.func = FsmTimeout;
330af57ed9fSAtsushi Murai   fp->FsmTimer.arg = (void *) fp;
331af57ed9fSAtsushi Murai   (fp->InitRestartCounter) (fp);
332af57ed9fSAtsushi Murai }
333af57ed9fSAtsushi Murai 
334af57ed9fSAtsushi Murai /*
335af57ed9fSAtsushi Murai  *   Actions when receive packets
336af57ed9fSAtsushi Murai  */
33775240ed1SBrian Somers static void
338944f7098SBrian Somers FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
339944f7098SBrian Somers /* RCR */
340af57ed9fSAtsushi Murai {
34153c9f6c0SAtsushi Murai   int plen, flen;
342af57ed9fSAtsushi Murai   int ackaction = 0;
343af57ed9fSAtsushi Murai 
344af57ed9fSAtsushi Murai   plen = plength(bp);
34553c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
34653c9f6c0SAtsushi Murai   if (plen < flen) {
347afc7fa2cSBrian Somers     LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)\n",
348afc7fa2cSBrian Somers 	      plen, flen);
349af57ed9fSAtsushi Murai     pfree(bp);
350af57ed9fSAtsushi Murai     return;
351af57ed9fSAtsushi Murai   }
352af57ed9fSAtsushi Murai 
353af57ed9fSAtsushi Murai   /*
354af57ed9fSAtsushi Murai    * Check and process easy case
355af57ed9fSAtsushi Murai    */
356af57ed9fSAtsushi Murai   switch (fp->state) {
357af57ed9fSAtsushi Murai   case ST_INITIAL:
358af57ed9fSAtsushi Murai   case ST_STARTING:
359cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]);
360af57ed9fSAtsushi Murai     pfree(bp);
361af57ed9fSAtsushi Murai     return;
362af57ed9fSAtsushi Murai   case ST_CLOSED:
363af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
364af57ed9fSAtsushi Murai     pfree(bp);
365af57ed9fSAtsushi Murai     return;
366af57ed9fSAtsushi Murai   case ST_CLOSING:
367af57ed9fSAtsushi Murai   case ST_STOPPING:
368927145beSBrian Somers     LogPrintf(LogERROR, "Got ConfigReq while state = %d\n", fp->state);
369af57ed9fSAtsushi Murai     pfree(bp);
370af57ed9fSAtsushi Murai     return;
371af57ed9fSAtsushi Murai   }
372af57ed9fSAtsushi Murai 
37353c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REQ);
374af57ed9fSAtsushi Murai 
375af57ed9fSAtsushi Murai   if (nakp == NakBuff && rejp == RejBuff)
376af57ed9fSAtsushi Murai     ackaction = 1;
377af57ed9fSAtsushi Murai 
378af57ed9fSAtsushi Murai   switch (fp->state) {
379af57ed9fSAtsushi Murai   case ST_OPENED:
380af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
381af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
382af57ed9fSAtsushi Murai     break;
383af57ed9fSAtsushi Murai   case ST_STOPPED:
384af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
385af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
386af57ed9fSAtsushi Murai     break;
387af57ed9fSAtsushi Murai   }
388af57ed9fSAtsushi Murai 
389af57ed9fSAtsushi Murai   if (rejp != RejBuff)
390af57ed9fSAtsushi Murai     FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff);
391af57ed9fSAtsushi Murai   if (nakp != NakBuff)
392af57ed9fSAtsushi Murai     FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff);
393af57ed9fSAtsushi Murai   if (ackaction)
394af57ed9fSAtsushi Murai     FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff);
395af57ed9fSAtsushi Murai 
396af57ed9fSAtsushi Murai   switch (fp->state) {
397af57ed9fSAtsushi Murai   case ST_STOPPED:
398af57ed9fSAtsushi Murai   case ST_OPENED:
399af57ed9fSAtsushi Murai     if (ackaction)
400af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
401af57ed9fSAtsushi Murai     else
402af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
403af57ed9fSAtsushi Murai     break;
404af57ed9fSAtsushi Murai   case ST_REQSENT:
405af57ed9fSAtsushi Murai     if (ackaction)
406af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
407af57ed9fSAtsushi Murai     break;
408af57ed9fSAtsushi Murai   case ST_ACKRCVD:
409af57ed9fSAtsushi Murai     if (ackaction) {
410af57ed9fSAtsushi Murai       NewState(fp, ST_OPENED);
411af57ed9fSAtsushi Murai       (fp->LayerUp) (fp);
412af57ed9fSAtsushi Murai     }
413af57ed9fSAtsushi Murai     break;
414af57ed9fSAtsushi Murai   case ST_ACKSENT:
415af57ed9fSAtsushi Murai     if (!ackaction)
416af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
417af57ed9fSAtsushi Murai     break;
418af57ed9fSAtsushi Murai   }
419af57ed9fSAtsushi Murai   pfree(bp);
420af57ed9fSAtsushi Murai }
421af57ed9fSAtsushi Murai 
42275240ed1SBrian Somers static void
423944f7098SBrian Somers FsmRecvConfigAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
424944f7098SBrian Somers /* RCA */
425af57ed9fSAtsushi Murai {
426af57ed9fSAtsushi Murai   switch (fp->state) {
427af57ed9fSAtsushi Murai     case ST_CLOSED:
428af57ed9fSAtsushi Murai     case ST_STOPPED:
429af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
430af57ed9fSAtsushi Murai     break;
431af57ed9fSAtsushi Murai   case ST_CLOSING:
432af57ed9fSAtsushi Murai   case ST_STOPPING:
433af57ed9fSAtsushi Murai     break;
434af57ed9fSAtsushi Murai   case ST_REQSENT:
435af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
436af57ed9fSAtsushi Murai     NewState(fp, ST_ACKRCVD);
437af57ed9fSAtsushi Murai     break;
438af57ed9fSAtsushi Murai   case ST_ACKRCVD:
439af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
440af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
441af57ed9fSAtsushi Murai     break;
442af57ed9fSAtsushi Murai   case ST_ACKSENT:
443af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
444af57ed9fSAtsushi Murai     NewState(fp, ST_OPENED);
445af57ed9fSAtsushi Murai     (fp->LayerUp) (fp);
446af57ed9fSAtsushi Murai     break;
447af57ed9fSAtsushi Murai   case ST_OPENED:
448af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
449af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
450af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
451af57ed9fSAtsushi Murai     break;
452af57ed9fSAtsushi Murai   }
453af57ed9fSAtsushi Murai   pfree(bp);
454af57ed9fSAtsushi Murai }
455af57ed9fSAtsushi Murai 
45675240ed1SBrian Somers static void
457944f7098SBrian Somers FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
458944f7098SBrian Somers /* RCN */
459af57ed9fSAtsushi Murai {
46053c9f6c0SAtsushi Murai   int plen, flen;
461af57ed9fSAtsushi Murai 
462af57ed9fSAtsushi Murai   plen = plength(bp);
46353c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
46453c9f6c0SAtsushi Murai   if (plen < flen) {
465af57ed9fSAtsushi Murai     pfree(bp);
466af57ed9fSAtsushi Murai     return;
467af57ed9fSAtsushi Murai   }
468af57ed9fSAtsushi Murai 
469af57ed9fSAtsushi Murai   /*
470af57ed9fSAtsushi Murai    * Check and process easy case
471af57ed9fSAtsushi Murai    */
472af57ed9fSAtsushi Murai   switch (fp->state) {
473af57ed9fSAtsushi Murai   case ST_INITIAL:
474af57ed9fSAtsushi Murai   case ST_STARTING:
475cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", StateNames[fp->state]);
476af57ed9fSAtsushi Murai     pfree(bp);
477af57ed9fSAtsushi Murai     return;
478af57ed9fSAtsushi Murai   case ST_CLOSED:
479af57ed9fSAtsushi Murai   case ST_STOPPED:
480af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
481af57ed9fSAtsushi Murai     pfree(bp);
482af57ed9fSAtsushi Murai     return;
483af57ed9fSAtsushi Murai   case ST_CLOSING:
484af57ed9fSAtsushi Murai   case ST_STOPPING:
485af57ed9fSAtsushi Murai     pfree(bp);
486af57ed9fSAtsushi Murai     return;
487af57ed9fSAtsushi Murai   }
488af57ed9fSAtsushi Murai 
48953c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_NAK);
490af57ed9fSAtsushi Murai 
491af57ed9fSAtsushi Murai   switch (fp->state) {
492af57ed9fSAtsushi Murai   case ST_REQSENT:
493af57ed9fSAtsushi Murai   case ST_ACKSENT:
494af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
495af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
496af57ed9fSAtsushi Murai     break;
497af57ed9fSAtsushi Murai   case ST_OPENED:
498af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
499af57ed9fSAtsushi Murai     /* Fall down */
500af57ed9fSAtsushi Murai   case ST_ACKRCVD:
501af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
502af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
503af57ed9fSAtsushi Murai     break;
504af57ed9fSAtsushi Murai   }
505af57ed9fSAtsushi Murai 
506af57ed9fSAtsushi Murai   pfree(bp);
507af57ed9fSAtsushi Murai }
508af57ed9fSAtsushi Murai 
50975240ed1SBrian Somers static void
510944f7098SBrian Somers FsmRecvTermReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
511944f7098SBrian Somers /* RTR */
512af57ed9fSAtsushi Murai {
513af57ed9fSAtsushi Murai   switch (fp->state) {
514af57ed9fSAtsushi Murai     case ST_INITIAL:
515af57ed9fSAtsushi Murai     case ST_STARTING:
516cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", StateNames[fp->state]);
517af57ed9fSAtsushi Murai     break;
518af57ed9fSAtsushi Murai   case ST_CLOSED:
519af57ed9fSAtsushi Murai   case ST_STOPPED:
520af57ed9fSAtsushi Murai   case ST_CLOSING:
521af57ed9fSAtsushi Murai   case ST_STOPPING:
522af57ed9fSAtsushi Murai   case ST_REQSENT:
523af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
524af57ed9fSAtsushi Murai     break;
525af57ed9fSAtsushi Murai   case ST_ACKRCVD:
526af57ed9fSAtsushi Murai   case ST_ACKSENT:
527af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
528af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
529af57ed9fSAtsushi Murai     break;
530af57ed9fSAtsushi Murai   case ST_OPENED:
5318f2fa0eeSBrian Somers     (fp->LayerDown) (fp);
532af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
5338f2fa0eeSBrian Somers     StartTimer(&fp->FsmTimer);	/* Start restart timer */
5348f2fa0eeSBrian Somers     fp->restart = 0;
5358f2fa0eeSBrian Somers     NewState(fp, ST_STOPPING);
536af57ed9fSAtsushi Murai     break;
537af57ed9fSAtsushi Murai   }
538af57ed9fSAtsushi Murai   pfree(bp);
539af57ed9fSAtsushi Murai }
540af57ed9fSAtsushi Murai 
54175240ed1SBrian Somers static void
542944f7098SBrian Somers FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
543944f7098SBrian Somers /* RTA */
544af57ed9fSAtsushi Murai {
545af57ed9fSAtsushi Murai   switch (fp->state) {
546af57ed9fSAtsushi Murai     case ST_CLOSING:
547af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
548af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
549af57ed9fSAtsushi Murai     break;
550af57ed9fSAtsushi Murai   case ST_STOPPING:
551af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPED);
552af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
553af57ed9fSAtsushi Murai     break;
554af57ed9fSAtsushi Murai   case ST_ACKRCVD:
555af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
556af57ed9fSAtsushi Murai     break;
557af57ed9fSAtsushi Murai   case ST_OPENED:
558af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
559af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
560af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
561af57ed9fSAtsushi Murai     break;
562af57ed9fSAtsushi Murai   }
563af57ed9fSAtsushi Murai   pfree(bp);
564af57ed9fSAtsushi Murai }
565af57ed9fSAtsushi Murai 
56675240ed1SBrian Somers static void
567944f7098SBrian Somers FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
568944f7098SBrian Somers /* RCJ */
569af57ed9fSAtsushi Murai {
57053c9f6c0SAtsushi Murai   int plen, flen;
571af57ed9fSAtsushi Murai 
572af57ed9fSAtsushi Murai   plen = plength(bp);
57353c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
57453c9f6c0SAtsushi Murai   if (plen < flen) {
575af57ed9fSAtsushi Murai     pfree(bp);
576af57ed9fSAtsushi Murai     return;
577af57ed9fSAtsushi Murai   }
578cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvConfigRej.\n");
579af57ed9fSAtsushi Murai 
580af57ed9fSAtsushi Murai   /*
581af57ed9fSAtsushi Murai    * Check and process easy case
582af57ed9fSAtsushi Murai    */
583af57ed9fSAtsushi Murai   switch (fp->state) {
584af57ed9fSAtsushi Murai   case ST_INITIAL:
585af57ed9fSAtsushi Murai   case ST_STARTING:
586cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", StateNames[fp->state]);
587af57ed9fSAtsushi Murai     pfree(bp);
588af57ed9fSAtsushi Murai     return;
589af57ed9fSAtsushi Murai   case ST_CLOSED:
590af57ed9fSAtsushi Murai   case ST_STOPPED:
591af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
592af57ed9fSAtsushi Murai     pfree(bp);
593af57ed9fSAtsushi Murai     return;
594af57ed9fSAtsushi Murai   case ST_CLOSING:
595af57ed9fSAtsushi Murai   case ST_STOPPING:
596af57ed9fSAtsushi Murai     pfree(bp);
597af57ed9fSAtsushi Murai     return;
598af57ed9fSAtsushi Murai   }
599af57ed9fSAtsushi Murai 
60053c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REJ);
601af57ed9fSAtsushi Murai 
602af57ed9fSAtsushi Murai   switch (fp->state) {
603af57ed9fSAtsushi Murai   case ST_REQSENT:
604af57ed9fSAtsushi Murai   case ST_ACKSENT:
605af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
606af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
607af57ed9fSAtsushi Murai     break;
608af57ed9fSAtsushi Murai   case ST_OPENED:
609af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
610af57ed9fSAtsushi Murai     /* Fall down */
611af57ed9fSAtsushi Murai   case ST_ACKRCVD:
612af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
613af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
614af57ed9fSAtsushi Murai     break;
615af57ed9fSAtsushi Murai   }
616af57ed9fSAtsushi Murai   pfree(bp);
617af57ed9fSAtsushi Murai }
618af57ed9fSAtsushi Murai 
61975240ed1SBrian Somers static void
620944f7098SBrian Somers FsmRecvCodeRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
621af57ed9fSAtsushi Murai {
622cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvCodeRej\n");
623af57ed9fSAtsushi Murai   pfree(bp);
624af57ed9fSAtsushi Murai }
625af57ed9fSAtsushi Murai 
62675240ed1SBrian Somers static void
627944f7098SBrian Somers FsmRecvProtoRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
628af57ed9fSAtsushi Murai {
629af57ed9fSAtsushi Murai   u_short *sp, proto;
630af57ed9fSAtsushi Murai 
631af57ed9fSAtsushi Murai   sp = (u_short *) MBUF_CTOP(bp);
632af57ed9fSAtsushi Murai   proto = ntohs(*sp);
633cb611434SBrian Somers   LogPrintf(fp->LogLevel, "-- Protocol (%04x) was rejected.\n", proto);
634af57ed9fSAtsushi Murai 
635af57ed9fSAtsushi Murai   switch (proto) {
636af57ed9fSAtsushi Murai   case PROTO_LQR:
637af57ed9fSAtsushi Murai     StopLqr(LQM_LQR);
638af57ed9fSAtsushi Murai     break;
639af57ed9fSAtsushi Murai   case PROTO_CCP:
640af57ed9fSAtsushi Murai     fp = &CcpFsm;
641af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
642af57ed9fSAtsushi Murai     switch (fp->state) {
643af57ed9fSAtsushi Murai     case ST_CLOSED:
644af57ed9fSAtsushi Murai     case ST_CLOSING:
645af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
646af57ed9fSAtsushi Murai     default:
647af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
648af57ed9fSAtsushi Murai       break;
649af57ed9fSAtsushi Murai     }
650af57ed9fSAtsushi Murai     break;
651af57ed9fSAtsushi Murai   }
652af57ed9fSAtsushi Murai   pfree(bp);
653af57ed9fSAtsushi Murai }
654af57ed9fSAtsushi Murai 
65575240ed1SBrian Somers static void
656944f7098SBrian Somers FsmRecvEchoReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
657af57ed9fSAtsushi Murai {
658af57ed9fSAtsushi Murai   u_char *cp;
659af57ed9fSAtsushi Murai   u_long *lp, magic;
660af57ed9fSAtsushi Murai 
661af57ed9fSAtsushi Murai   cp = MBUF_CTOP(bp);
662af57ed9fSAtsushi Murai   lp = (u_long *) cp;
663af57ed9fSAtsushi Murai   magic = ntohl(*lp);
664af57ed9fSAtsushi Murai   if (magic != LcpInfo.his_magic) {
665927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n");
666af57ed9fSAtsushi Murai     /* XXX: We should send terminate request */
667af57ed9fSAtsushi Murai   }
668af57ed9fSAtsushi Murai   if (fp->state == ST_OPENED) {
669af57ed9fSAtsushi Murai     *lp = htonl(LcpInfo.want_magic);	/* Insert local magic number */
670cb611434SBrian Somers     LogPrintf(fp->LogLevel, "SendEchoRep(%s)\n", StateNames[fp->state]);
671af57ed9fSAtsushi Murai     FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp));
672af57ed9fSAtsushi Murai   }
673af57ed9fSAtsushi Murai   pfree(bp);
674af57ed9fSAtsushi Murai }
675af57ed9fSAtsushi Murai 
67675240ed1SBrian Somers static void
677944f7098SBrian Somers FsmRecvEchoRep(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
678af57ed9fSAtsushi Murai {
679af57ed9fSAtsushi Murai   u_long *lp, magic;
680af57ed9fSAtsushi Murai 
681af57ed9fSAtsushi Murai   lp = (u_long *) MBUF_CTOP(bp);
682af57ed9fSAtsushi Murai   magic = ntohl(*lp);
68385c59f05SJoerg Wunsch /*
68485c59f05SJoerg Wunsch  * Tolerate echo replies with either magic number
68585c59f05SJoerg Wunsch  */
68685c59f05SJoerg Wunsch   if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) {
687927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n",
688af57ed9fSAtsushi Murai 	      LcpInfo.his_magic, magic);
689944f7098SBrian Somers 
690af57ed9fSAtsushi Murai     /*
691944f7098SBrian Somers      * XXX: We should send terminate request. But poor implementation may die
692944f7098SBrian Somers      * as a result.
693af57ed9fSAtsushi Murai      */
694af57ed9fSAtsushi Murai   }
695af57ed9fSAtsushi Murai   RecvEchoLqr(bp);
696af57ed9fSAtsushi Murai   pfree(bp);
697af57ed9fSAtsushi Murai }
698af57ed9fSAtsushi Murai 
69975240ed1SBrian Somers static void
700944f7098SBrian Somers FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
701af57ed9fSAtsushi Murai {
702cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvDiscReq\n");
703af57ed9fSAtsushi Murai   pfree(bp);
704af57ed9fSAtsushi Murai }
705af57ed9fSAtsushi Murai 
70675240ed1SBrian Somers static void
707944f7098SBrian Somers FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
708af57ed9fSAtsushi Murai {
709cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvIdent\n");
710af57ed9fSAtsushi Murai   pfree(bp);
711af57ed9fSAtsushi Murai }
712af57ed9fSAtsushi Murai 
71375240ed1SBrian Somers static void
714944f7098SBrian Somers FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
715af57ed9fSAtsushi Murai {
716cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvTimeRemain\n");
717af57ed9fSAtsushi Murai   pfree(bp);
718af57ed9fSAtsushi Murai }
719af57ed9fSAtsushi Murai 
72075240ed1SBrian Somers static void
721944f7098SBrian Somers FsmRecvResetReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
722af57ed9fSAtsushi Murai {
723cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetReq\n");
724af57ed9fSAtsushi Murai   CcpRecvResetReq(fp);
725cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendResetAck\n");
726af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0);
727af57ed9fSAtsushi Murai   pfree(bp);
728af57ed9fSAtsushi Murai }
729af57ed9fSAtsushi Murai 
73075240ed1SBrian Somers static void
731944f7098SBrian Somers FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
732af57ed9fSAtsushi Murai {
733cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetAck\n");
73429a6597cSBrian Somers   Pred1Init(1);			/* Initialize Input part */
735af57ed9fSAtsushi Murai   fp->reqid++;
736af57ed9fSAtsushi Murai   pfree(bp);
737af57ed9fSAtsushi Murai }
738af57ed9fSAtsushi Murai 
739af57ed9fSAtsushi Murai struct fsmcodedesc FsmCodes[] = {
740af57ed9fSAtsushi Murai   {FsmRecvConfigReq, "Configure Request",},
741af57ed9fSAtsushi Murai   {FsmRecvConfigAck, "Configure Ack",},
742af57ed9fSAtsushi Murai   {FsmRecvConfigNak, "Configure Nak",},
743af57ed9fSAtsushi Murai   {FsmRecvConfigRej, "Configure Reject",},
744af57ed9fSAtsushi Murai   {FsmRecvTermReq, "Terminate Request",},
745af57ed9fSAtsushi Murai   {FsmRecvTermAck, "Terminate Ack",},
746af57ed9fSAtsushi Murai   {FsmRecvCodeRej, "Code Reject",},
747af57ed9fSAtsushi Murai   {FsmRecvProtoRej, "Protocol Reject",},
748af57ed9fSAtsushi Murai   {FsmRecvEchoReq, "Echo Request",},
749af57ed9fSAtsushi Murai   {FsmRecvEchoRep, "Echo Reply",},
750af57ed9fSAtsushi Murai   {FsmRecvDiscReq, "Discard Request",},
751af57ed9fSAtsushi Murai   {FsmRecvIdent, "Ident",},
752af57ed9fSAtsushi Murai   {FsmRecvTimeRemain, "Time Remain",},
753af57ed9fSAtsushi Murai   {FsmRecvResetReq, "Reset Request",},
754af57ed9fSAtsushi Murai   {FsmRecvResetAck, "Reset Ack",},
755af57ed9fSAtsushi Murai };
756af57ed9fSAtsushi Murai 
757af57ed9fSAtsushi Murai void
758944f7098SBrian Somers FsmInput(struct fsm * fp, struct mbuf * bp)
759af57ed9fSAtsushi Murai {
760af57ed9fSAtsushi Murai   int len;
761af57ed9fSAtsushi Murai   struct fsmheader *lhp;
762af57ed9fSAtsushi Murai   struct fsmcodedesc *codep;
763af57ed9fSAtsushi Murai 
764af57ed9fSAtsushi Murai   len = plength(bp);
765af57ed9fSAtsushi Murai   if (len < sizeof(struct fsmheader)) {
766af57ed9fSAtsushi Murai     pfree(bp);
767af57ed9fSAtsushi Murai     return;
768af57ed9fSAtsushi Murai   }
769af57ed9fSAtsushi Murai   lhp = (struct fsmheader *) MBUF_CTOP(bp);
770af57ed9fSAtsushi Murai   if (lhp->code == 0 || lhp->code > fp->max_code) {
771af57ed9fSAtsushi Murai     pfree(bp);			/* XXX: Should send code reject */
772af57ed9fSAtsushi Murai     return;
773af57ed9fSAtsushi Murai   }
774af57ed9fSAtsushi Murai   bp->offset += sizeof(struct fsmheader);
775af57ed9fSAtsushi Murai   bp->cnt -= sizeof(struct fsmheader);
776af57ed9fSAtsushi Murai 
777af57ed9fSAtsushi Murai   codep = FsmCodes + lhp->code - 1;
778cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n",
779927145beSBrian Somers 	    codep->name, lhp->id, StateNames[fp->state], fp->state);
780927145beSBrian Somers   if (LogIsKept(LogDEBUG))
781af57ed9fSAtsushi Murai     LogMemory();
782af57ed9fSAtsushi Murai   (codep->action) (fp, lhp, bp);
783927145beSBrian Somers   if (LogIsKept(LogDEBUG))
784af57ed9fSAtsushi Murai     LogMemory();
785af57ed9fSAtsushi Murai }
786