xref: /freebsd/usr.sbin/ppp/fsm.c (revision b6e82f33ef84ba5eedb0db2e24525e9d0f661b91)
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  *
20b6e82f33SBrian Somers  * $Id: fsm.c,v 1.21 1997/11/11 23:23:11 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 
33b6e82f33SBrian Somers #include "command.h"
3475240ed1SBrian Somers #include "mbuf.h"
3575240ed1SBrian Somers #include "log.h"
3675240ed1SBrian Somers #include "defs.h"
3775240ed1SBrian Somers #include "timer.h"
38af57ed9fSAtsushi Murai #include "fsm.h"
39af57ed9fSAtsushi Murai #include "hdlc.h"
40af57ed9fSAtsushi Murai #include "lqr.h"
41af57ed9fSAtsushi Murai #include "lcpproto.h"
42af57ed9fSAtsushi Murai #include "lcp.h"
43ed6a16c1SPoul-Henning Kamp #include "ccp.h"
4471144dc5SBrian Somers #include "modem.h"
4571144dc5SBrian Somers #include "loadalias.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
67b6e82f33SBrian Somers StoppedTimeout(void *v)
6871144dc5SBrian Somers {
69b6e82f33SBrian Somers   struct fsm *fp = (struct fsm *)v;
70b6e82f33SBrian Somers 
71cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Stopped timer expired\n");
7271144dc5SBrian Somers   if (modem != -1)
7371144dc5SBrian Somers     DownConnection();
7471144dc5SBrian Somers   else
7571144dc5SBrian Somers     FsmDown(fp);
7671144dc5SBrian Somers }
7771144dc5SBrian Somers 
78af57ed9fSAtsushi Murai void
79944f7098SBrian Somers FsmInit(struct fsm * fp)
80af57ed9fSAtsushi Murai {
81927145beSBrian Somers   LogPrintf(LogDEBUG, "FsmInit\n");
82af57ed9fSAtsushi Murai   fp->state = ST_INITIAL;
83af57ed9fSAtsushi Murai   fp->reqid = 1;
84af57ed9fSAtsushi Murai   fp->restart = 1;
85af57ed9fSAtsushi Murai   fp->maxconfig = 3;
86af57ed9fSAtsushi Murai }
87af57ed9fSAtsushi Murai 
8875240ed1SBrian Somers static void
89944f7098SBrian Somers NewState(struct fsm * fp, int new)
90af57ed9fSAtsushi Murai {
91cb611434SBrian Somers   LogPrintf(fp->LogLevel, "State change %s --> %s\n",
92927145beSBrian Somers 	    StateNames[fp->state], StateNames[new]);
93cb611434SBrian Somers   if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
94cb611434SBrian Somers     StopTimer(&fp->StoppedTimer);
95af57ed9fSAtsushi Murai   fp->state = new;
9671144dc5SBrian Somers   if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
97af57ed9fSAtsushi Murai     StopTimer(&fp->FsmTimer);
98cb611434SBrian Somers     if (new == ST_STOPPED && fp->StoppedTimer.load) {
99cb611434SBrian Somers       fp->StoppedTimer.state = TIMER_STOPPED;
100cb611434SBrian Somers       fp->StoppedTimer.func = StoppedTimeout;
101cb611434SBrian Somers       fp->StoppedTimer.arg = (void *) fp;
102cb611434SBrian Somers       StartTimer(&fp->StoppedTimer);
10371144dc5SBrian Somers     }
10471144dc5SBrian Somers   }
105af57ed9fSAtsushi Murai }
106af57ed9fSAtsushi Murai 
107af57ed9fSAtsushi Murai void
108944f7098SBrian Somers FsmOutput(struct fsm * fp, u_int code, u_int id, u_char * ptr, int count)
109af57ed9fSAtsushi Murai {
110af57ed9fSAtsushi Murai   int plen;
111af57ed9fSAtsushi Murai   struct fsmheader lh;
112af57ed9fSAtsushi Murai   struct mbuf *bp;
113af57ed9fSAtsushi Murai 
114af57ed9fSAtsushi Murai   plen = sizeof(struct fsmheader) + count;
115af57ed9fSAtsushi Murai   lh.code = code;
116af57ed9fSAtsushi Murai   lh.id = id;
117af57ed9fSAtsushi Murai   lh.length = htons(plen);
118af57ed9fSAtsushi Murai   bp = mballoc(plen, MB_FSM);
11975240ed1SBrian Somers   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
120af57ed9fSAtsushi Murai   if (count)
12175240ed1SBrian Somers     memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
122927145beSBrian Somers   LogDumpBp(LogDEBUG, "FsmOutput", bp);
12376bd0c0aSDoug Rabson   HdlcOutput(PRI_LINK, fp->proto, bp);
124af57ed9fSAtsushi Murai }
125af57ed9fSAtsushi Murai 
126af57ed9fSAtsushi Murai void
127944f7098SBrian Somers FsmOpen(struct fsm * fp)
128af57ed9fSAtsushi Murai {
129af57ed9fSAtsushi Murai   switch (fp->state) {
130af57ed9fSAtsushi Murai     case ST_INITIAL:
131af57ed9fSAtsushi Murai     (fp->LayerStart) (fp);
132af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
133af57ed9fSAtsushi Murai     break;
134af57ed9fSAtsushi Murai   case ST_STARTING:
135af57ed9fSAtsushi Murai     break;
136af57ed9fSAtsushi Murai   case ST_CLOSED:
137af57ed9fSAtsushi Murai     if (fp->open_mode == OPEN_PASSIVE) {
138af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
139af57ed9fSAtsushi Murai     } else {
140af57ed9fSAtsushi Murai       FsmInitRestartCounter(fp);
141af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
142af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
143af57ed9fSAtsushi Murai     }
144af57ed9fSAtsushi Murai     break;
145af57ed9fSAtsushi Murai   case ST_STOPPED:		/* XXX: restart option */
146af57ed9fSAtsushi Murai   case ST_REQSENT:
147af57ed9fSAtsushi Murai   case ST_ACKRCVD:
148af57ed9fSAtsushi Murai   case ST_ACKSENT:
149af57ed9fSAtsushi Murai   case ST_OPENED:		/* XXX: restart option */
150af57ed9fSAtsushi Murai     break;
151af57ed9fSAtsushi Murai   case ST_CLOSING:		/* XXX: restart option */
152af57ed9fSAtsushi Murai   case ST_STOPPING:		/* XXX: restart option */
153af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPING);
154af57ed9fSAtsushi Murai     break;
155af57ed9fSAtsushi Murai   }
156af57ed9fSAtsushi Murai }
157af57ed9fSAtsushi Murai 
158af57ed9fSAtsushi Murai void
159944f7098SBrian Somers FsmUp(struct fsm * fp)
160af57ed9fSAtsushi Murai {
161af57ed9fSAtsushi Murai   switch (fp->state) {
162af57ed9fSAtsushi Murai     case ST_INITIAL:
163af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
164af57ed9fSAtsushi Murai     break;
165af57ed9fSAtsushi Murai   case ST_STARTING:
166af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
167af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
168af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
169af57ed9fSAtsushi Murai     break;
170af57ed9fSAtsushi Murai   default:
171cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]);
172af57ed9fSAtsushi Murai     break;
173af57ed9fSAtsushi Murai   }
174af57ed9fSAtsushi Murai }
175af57ed9fSAtsushi Murai 
176af57ed9fSAtsushi Murai void
177944f7098SBrian Somers FsmDown(struct fsm * fp)
178af57ed9fSAtsushi Murai {
179af57ed9fSAtsushi Murai   switch (fp->state) {
180af57ed9fSAtsushi Murai     case ST_CLOSED:
181af57ed9fSAtsushi Murai     case ST_CLOSING:
182af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
183af57ed9fSAtsushi Murai     break;
184af57ed9fSAtsushi Murai   case ST_STOPPED:
185af57ed9fSAtsushi Murai     (fp->LayerStart) (fp);
186af57ed9fSAtsushi Murai     /* Fall into.. */
187af57ed9fSAtsushi Murai   case ST_STOPPING:
188af57ed9fSAtsushi Murai   case ST_REQSENT:
189af57ed9fSAtsushi Murai   case ST_ACKRCVD:
190af57ed9fSAtsushi Murai   case ST_ACKSENT:
191af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
192af57ed9fSAtsushi Murai     break;
193af57ed9fSAtsushi Murai   case ST_OPENED:
194af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
195af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
196af57ed9fSAtsushi Murai     break;
197af57ed9fSAtsushi Murai   }
198af57ed9fSAtsushi Murai }
199af57ed9fSAtsushi Murai 
200af57ed9fSAtsushi Murai void
201944f7098SBrian Somers FsmClose(struct fsm * fp)
202af57ed9fSAtsushi Murai {
203af57ed9fSAtsushi Murai   switch (fp->state) {
204af57ed9fSAtsushi Murai     case ST_STARTING:
205af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
206af57ed9fSAtsushi Murai     break;
207af57ed9fSAtsushi Murai   case ST_STOPPED:
208af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
209af57ed9fSAtsushi Murai     break;
210af57ed9fSAtsushi Murai   case ST_STOPPING:
211af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
212af57ed9fSAtsushi Murai     break;
213af57ed9fSAtsushi Murai   case ST_OPENED:
214af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
215af57ed9fSAtsushi Murai     /* Fall down */
216af57ed9fSAtsushi Murai   case ST_REQSENT:
217af57ed9fSAtsushi Murai   case ST_ACKRCVD:
218af57ed9fSAtsushi Murai   case ST_ACKSENT:
219af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
220af57ed9fSAtsushi Murai     FsmSendTerminateReq(fp);
221af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
222af57ed9fSAtsushi Murai     break;
223af57ed9fSAtsushi Murai   }
224af57ed9fSAtsushi Murai }
225af57ed9fSAtsushi Murai 
226af57ed9fSAtsushi Murai /*
227af57ed9fSAtsushi Murai  *	Send functions
228af57ed9fSAtsushi Murai  */
22975240ed1SBrian Somers static void
230944f7098SBrian Somers FsmSendConfigReq(struct fsm * fp)
231af57ed9fSAtsushi Murai {
232af57ed9fSAtsushi Murai   if (--fp->maxconfig > 0) {
233af57ed9fSAtsushi Murai     (fp->SendConfigReq) (fp);
234af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);	/* Start restart timer */
235af57ed9fSAtsushi Murai     fp->restart--;		/* Decrement restart counter */
236af57ed9fSAtsushi Murai   } else {
237af57ed9fSAtsushi Murai     FsmClose(fp);
238af57ed9fSAtsushi Murai   }
239af57ed9fSAtsushi Murai }
240af57ed9fSAtsushi Murai 
24175240ed1SBrian Somers static void
242944f7098SBrian Somers FsmSendTerminateReq(struct fsm * fp)
243af57ed9fSAtsushi Murai {
244cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendTerminateReq.\n");
245af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
246af57ed9fSAtsushi Murai   (fp->SendTerminateReq) (fp);
247af57ed9fSAtsushi Murai   StartTimer(&fp->FsmTimer);	/* Start restart timer */
248af57ed9fSAtsushi Murai   fp->restart--;		/* Decrement restart counter */
249af57ed9fSAtsushi Murai }
250af57ed9fSAtsushi Murai 
251af57ed9fSAtsushi Murai static void
252944f7098SBrian Somers FsmSendConfigAck(struct fsm * fp,
253944f7098SBrian Somers 		 struct fsmheader * lhp,
254944f7098SBrian Somers 		 u_char * option,
255944f7098SBrian Somers 		 int count)
256af57ed9fSAtsushi Murai {
257cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]);
25853c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
259af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
260af57ed9fSAtsushi Murai }
261af57ed9fSAtsushi Murai 
262af57ed9fSAtsushi Murai static void
263944f7098SBrian Somers FsmSendConfigRej(struct fsm * fp,
264944f7098SBrian Somers 		 struct fsmheader * lhp,
265944f7098SBrian Somers 		 u_char * option,
266944f7098SBrian Somers 		 int count)
267af57ed9fSAtsushi Murai {
268cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]);
26953c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
270af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
271af57ed9fSAtsushi Murai }
272af57ed9fSAtsushi Murai 
273af57ed9fSAtsushi Murai static void
274944f7098SBrian Somers FsmSendConfigNak(struct fsm * fp,
275944f7098SBrian Somers 		 struct fsmheader * lhp,
276944f7098SBrian Somers 		 u_char * option,
277944f7098SBrian Somers 		 int count)
278af57ed9fSAtsushi Murai {
279cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]);
28053c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
281af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
282af57ed9fSAtsushi Murai }
283af57ed9fSAtsushi Murai 
284af57ed9fSAtsushi Murai /*
285af57ed9fSAtsushi Murai  *	Timeout actions
286af57ed9fSAtsushi Murai  */
28775240ed1SBrian Somers static void
288b6e82f33SBrian Somers FsmTimeout(void *v)
289af57ed9fSAtsushi Murai {
290b6e82f33SBrian Somers   struct fsm *fp = (struct fsm *)v;
291b6e82f33SBrian Somers 
292af57ed9fSAtsushi Murai   if (fp->restart) {
293af57ed9fSAtsushi Murai     switch (fp->state) {
294af57ed9fSAtsushi Murai       case ST_CLOSING:
295af57ed9fSAtsushi Murai       case ST_STOPPING:
296af57ed9fSAtsushi Murai       FsmSendTerminateReq(fp);
297af57ed9fSAtsushi Murai       break;
298af57ed9fSAtsushi Murai     case ST_REQSENT:
299af57ed9fSAtsushi Murai     case ST_ACKSENT:
300af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
301af57ed9fSAtsushi Murai       break;
302af57ed9fSAtsushi Murai     case ST_ACKRCVD:
303af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
304af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
305af57ed9fSAtsushi Murai       break;
306af57ed9fSAtsushi Murai     }
307af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);
308af57ed9fSAtsushi Murai   } else {
309af57ed9fSAtsushi Murai     switch (fp->state) {
310af57ed9fSAtsushi Murai     case ST_CLOSING:
311af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
312af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
313af57ed9fSAtsushi Murai       break;
314af57ed9fSAtsushi Murai     case ST_STOPPING:
315af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
316af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
317af57ed9fSAtsushi Murai       break;
318af57ed9fSAtsushi Murai     case ST_REQSENT:		/* XXX: 3p */
319af57ed9fSAtsushi Murai     case ST_ACKSENT:
320af57ed9fSAtsushi Murai     case ST_ACKRCVD:
321af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
322af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
323af57ed9fSAtsushi Murai       break;
324af57ed9fSAtsushi Murai     }
325af57ed9fSAtsushi Murai   }
326af57ed9fSAtsushi Murai }
327af57ed9fSAtsushi Murai 
32875240ed1SBrian Somers static void
329944f7098SBrian Somers FsmInitRestartCounter(struct fsm * fp)
330af57ed9fSAtsushi Murai {
331af57ed9fSAtsushi Murai   StopTimer(&fp->FsmTimer);
332af57ed9fSAtsushi Murai   fp->FsmTimer.state = TIMER_STOPPED;
333af57ed9fSAtsushi Murai   fp->FsmTimer.func = FsmTimeout;
334af57ed9fSAtsushi Murai   fp->FsmTimer.arg = (void *) fp;
335af57ed9fSAtsushi Murai   (fp->InitRestartCounter) (fp);
336af57ed9fSAtsushi Murai }
337af57ed9fSAtsushi Murai 
338af57ed9fSAtsushi Murai /*
339af57ed9fSAtsushi Murai  *   Actions when receive packets
340af57ed9fSAtsushi Murai  */
34175240ed1SBrian Somers static void
342944f7098SBrian Somers FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
343944f7098SBrian Somers /* RCR */
344af57ed9fSAtsushi Murai {
34553c9f6c0SAtsushi Murai   int plen, flen;
346af57ed9fSAtsushi Murai   int ackaction = 0;
347af57ed9fSAtsushi Murai 
348af57ed9fSAtsushi Murai   plen = plength(bp);
34953c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
35053c9f6c0SAtsushi Murai   if (plen < flen) {
351afc7fa2cSBrian Somers     LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)\n",
352afc7fa2cSBrian Somers 	      plen, flen);
353af57ed9fSAtsushi Murai     pfree(bp);
354af57ed9fSAtsushi Murai     return;
355af57ed9fSAtsushi Murai   }
356af57ed9fSAtsushi Murai 
357af57ed9fSAtsushi Murai   /*
358af57ed9fSAtsushi Murai    * Check and process easy case
359af57ed9fSAtsushi Murai    */
360af57ed9fSAtsushi Murai   switch (fp->state) {
361af57ed9fSAtsushi Murai   case ST_INITIAL:
362af57ed9fSAtsushi Murai   case ST_STARTING:
363cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]);
364af57ed9fSAtsushi Murai     pfree(bp);
365af57ed9fSAtsushi Murai     return;
366af57ed9fSAtsushi Murai   case ST_CLOSED:
367af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
368af57ed9fSAtsushi Murai     pfree(bp);
369af57ed9fSAtsushi Murai     return;
370af57ed9fSAtsushi Murai   case ST_CLOSING:
371927145beSBrian Somers     LogPrintf(LogERROR, "Got ConfigReq while state = %d\n", fp->state);
372a9c503afSBrian Somers   case ST_STOPPING:
373af57ed9fSAtsushi Murai     pfree(bp);
374af57ed9fSAtsushi Murai     return;
375af57ed9fSAtsushi Murai   }
376af57ed9fSAtsushi Murai 
37753c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REQ);
378af57ed9fSAtsushi Murai 
379af57ed9fSAtsushi Murai   if (nakp == NakBuff && rejp == RejBuff)
380af57ed9fSAtsushi Murai     ackaction = 1;
381af57ed9fSAtsushi Murai 
382af57ed9fSAtsushi Murai   switch (fp->state) {
383af57ed9fSAtsushi Murai   case ST_OPENED:
384af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
385af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
386af57ed9fSAtsushi Murai     break;
387af57ed9fSAtsushi Murai   case ST_STOPPED:
388af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
389af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
390af57ed9fSAtsushi Murai     break;
391af57ed9fSAtsushi Murai   }
392af57ed9fSAtsushi Murai 
393af57ed9fSAtsushi Murai   if (rejp != RejBuff)
394af57ed9fSAtsushi Murai     FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff);
395af57ed9fSAtsushi Murai   if (nakp != NakBuff)
396af57ed9fSAtsushi Murai     FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff);
397af57ed9fSAtsushi Murai   if (ackaction)
398af57ed9fSAtsushi Murai     FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff);
399af57ed9fSAtsushi Murai 
400af57ed9fSAtsushi Murai   switch (fp->state) {
401af57ed9fSAtsushi Murai   case ST_STOPPED:
402af57ed9fSAtsushi Murai   case ST_OPENED:
403af57ed9fSAtsushi Murai     if (ackaction)
404af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
405af57ed9fSAtsushi Murai     else
406af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
407af57ed9fSAtsushi Murai     break;
408af57ed9fSAtsushi Murai   case ST_REQSENT:
409af57ed9fSAtsushi Murai     if (ackaction)
410af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
411af57ed9fSAtsushi Murai     break;
412af57ed9fSAtsushi Murai   case ST_ACKRCVD:
413af57ed9fSAtsushi Murai     if (ackaction) {
414af57ed9fSAtsushi Murai       NewState(fp, ST_OPENED);
415af57ed9fSAtsushi Murai       (fp->LayerUp) (fp);
416af57ed9fSAtsushi Murai     }
417af57ed9fSAtsushi Murai     break;
418af57ed9fSAtsushi Murai   case ST_ACKSENT:
419af57ed9fSAtsushi Murai     if (!ackaction)
420af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
421af57ed9fSAtsushi Murai     break;
422af57ed9fSAtsushi Murai   }
423af57ed9fSAtsushi Murai   pfree(bp);
424af57ed9fSAtsushi Murai }
425af57ed9fSAtsushi Murai 
42675240ed1SBrian Somers static void
427944f7098SBrian Somers FsmRecvConfigAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
428944f7098SBrian Somers /* RCA */
429af57ed9fSAtsushi Murai {
430af57ed9fSAtsushi Murai   switch (fp->state) {
431af57ed9fSAtsushi Murai     case ST_CLOSED:
432af57ed9fSAtsushi Murai     case ST_STOPPED:
433af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
434af57ed9fSAtsushi Murai     break;
435af57ed9fSAtsushi Murai   case ST_CLOSING:
436af57ed9fSAtsushi Murai   case ST_STOPPING:
437af57ed9fSAtsushi Murai     break;
438af57ed9fSAtsushi Murai   case ST_REQSENT:
439af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
440af57ed9fSAtsushi Murai     NewState(fp, ST_ACKRCVD);
441af57ed9fSAtsushi Murai     break;
442af57ed9fSAtsushi Murai   case ST_ACKRCVD:
443af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
444af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
445af57ed9fSAtsushi Murai     break;
446af57ed9fSAtsushi Murai   case ST_ACKSENT:
447af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
448af57ed9fSAtsushi Murai     NewState(fp, ST_OPENED);
449af57ed9fSAtsushi Murai     (fp->LayerUp) (fp);
450af57ed9fSAtsushi Murai     break;
451af57ed9fSAtsushi Murai   case ST_OPENED:
452af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
453af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
454af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
455af57ed9fSAtsushi Murai     break;
456af57ed9fSAtsushi Murai   }
457af57ed9fSAtsushi Murai   pfree(bp);
458af57ed9fSAtsushi Murai }
459af57ed9fSAtsushi Murai 
46075240ed1SBrian Somers static void
461944f7098SBrian Somers FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
462944f7098SBrian Somers /* RCN */
463af57ed9fSAtsushi Murai {
46453c9f6c0SAtsushi Murai   int plen, flen;
465af57ed9fSAtsushi Murai 
466af57ed9fSAtsushi Murai   plen = plength(bp);
46753c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
46853c9f6c0SAtsushi Murai   if (plen < flen) {
469af57ed9fSAtsushi Murai     pfree(bp);
470af57ed9fSAtsushi Murai     return;
471af57ed9fSAtsushi Murai   }
472af57ed9fSAtsushi Murai 
473af57ed9fSAtsushi Murai   /*
474af57ed9fSAtsushi Murai    * Check and process easy case
475af57ed9fSAtsushi Murai    */
476af57ed9fSAtsushi Murai   switch (fp->state) {
477af57ed9fSAtsushi Murai   case ST_INITIAL:
478af57ed9fSAtsushi Murai   case ST_STARTING:
479cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", StateNames[fp->state]);
480af57ed9fSAtsushi Murai     pfree(bp);
481af57ed9fSAtsushi Murai     return;
482af57ed9fSAtsushi Murai   case ST_CLOSED:
483af57ed9fSAtsushi Murai   case ST_STOPPED:
484af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
485af57ed9fSAtsushi Murai     pfree(bp);
486af57ed9fSAtsushi Murai     return;
487af57ed9fSAtsushi Murai   case ST_CLOSING:
488af57ed9fSAtsushi Murai   case ST_STOPPING:
489af57ed9fSAtsushi Murai     pfree(bp);
490af57ed9fSAtsushi Murai     return;
491af57ed9fSAtsushi Murai   }
492af57ed9fSAtsushi Murai 
49353c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_NAK);
494af57ed9fSAtsushi Murai 
495af57ed9fSAtsushi Murai   switch (fp->state) {
496af57ed9fSAtsushi Murai   case ST_REQSENT:
497af57ed9fSAtsushi Murai   case ST_ACKSENT:
498af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
499af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
500af57ed9fSAtsushi Murai     break;
501af57ed9fSAtsushi Murai   case ST_OPENED:
502af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
503af57ed9fSAtsushi Murai     /* Fall down */
504af57ed9fSAtsushi Murai   case ST_ACKRCVD:
505af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
506af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
507af57ed9fSAtsushi Murai     break;
508af57ed9fSAtsushi Murai   }
509af57ed9fSAtsushi Murai 
510af57ed9fSAtsushi Murai   pfree(bp);
511af57ed9fSAtsushi Murai }
512af57ed9fSAtsushi Murai 
51375240ed1SBrian Somers static void
514944f7098SBrian Somers FsmRecvTermReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
515944f7098SBrian Somers /* RTR */
516af57ed9fSAtsushi Murai {
517af57ed9fSAtsushi Murai   switch (fp->state) {
518af57ed9fSAtsushi Murai     case ST_INITIAL:
519af57ed9fSAtsushi Murai     case ST_STARTING:
520cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", StateNames[fp->state]);
521af57ed9fSAtsushi Murai     break;
522af57ed9fSAtsushi Murai   case ST_CLOSED:
523af57ed9fSAtsushi Murai   case ST_STOPPED:
524af57ed9fSAtsushi Murai   case ST_CLOSING:
525af57ed9fSAtsushi Murai   case ST_STOPPING:
526af57ed9fSAtsushi Murai   case ST_REQSENT:
527af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
528af57ed9fSAtsushi Murai     break;
529af57ed9fSAtsushi Murai   case ST_ACKRCVD:
530af57ed9fSAtsushi Murai   case ST_ACKSENT:
531af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
532af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
533af57ed9fSAtsushi Murai     break;
534af57ed9fSAtsushi Murai   case ST_OPENED:
5358f2fa0eeSBrian Somers     (fp->LayerDown) (fp);
536af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
5378f2fa0eeSBrian Somers     StartTimer(&fp->FsmTimer);	/* Start restart timer */
5388f2fa0eeSBrian Somers     fp->restart = 0;
5398f2fa0eeSBrian Somers     NewState(fp, ST_STOPPING);
540af57ed9fSAtsushi Murai     break;
541af57ed9fSAtsushi Murai   }
542af57ed9fSAtsushi Murai   pfree(bp);
543af57ed9fSAtsushi Murai }
544af57ed9fSAtsushi Murai 
54575240ed1SBrian Somers static void
546944f7098SBrian Somers FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
547944f7098SBrian Somers /* RTA */
548af57ed9fSAtsushi Murai {
549af57ed9fSAtsushi Murai   switch (fp->state) {
550af57ed9fSAtsushi Murai     case ST_CLOSING:
551af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
552af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
553af57ed9fSAtsushi Murai     break;
554af57ed9fSAtsushi Murai   case ST_STOPPING:
555af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPED);
556af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
557af57ed9fSAtsushi Murai     break;
558af57ed9fSAtsushi Murai   case ST_ACKRCVD:
559af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
560af57ed9fSAtsushi Murai     break;
561af57ed9fSAtsushi Murai   case ST_OPENED:
562af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
563af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
564af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
565af57ed9fSAtsushi Murai     break;
566af57ed9fSAtsushi Murai   }
567af57ed9fSAtsushi Murai   pfree(bp);
568af57ed9fSAtsushi Murai }
569af57ed9fSAtsushi Murai 
57075240ed1SBrian Somers static void
571944f7098SBrian Somers FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
572944f7098SBrian Somers /* RCJ */
573af57ed9fSAtsushi Murai {
57453c9f6c0SAtsushi Murai   int plen, flen;
575af57ed9fSAtsushi Murai 
576af57ed9fSAtsushi Murai   plen = plength(bp);
57753c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
57853c9f6c0SAtsushi Murai   if (plen < flen) {
579af57ed9fSAtsushi Murai     pfree(bp);
580af57ed9fSAtsushi Murai     return;
581af57ed9fSAtsushi Murai   }
582cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvConfigRej.\n");
583af57ed9fSAtsushi Murai 
584af57ed9fSAtsushi Murai   /*
585af57ed9fSAtsushi Murai    * Check and process easy case
586af57ed9fSAtsushi Murai    */
587af57ed9fSAtsushi Murai   switch (fp->state) {
588af57ed9fSAtsushi Murai   case ST_INITIAL:
589af57ed9fSAtsushi Murai   case ST_STARTING:
590cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", StateNames[fp->state]);
591af57ed9fSAtsushi Murai     pfree(bp);
592af57ed9fSAtsushi Murai     return;
593af57ed9fSAtsushi Murai   case ST_CLOSED:
594af57ed9fSAtsushi Murai   case ST_STOPPED:
595af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
596af57ed9fSAtsushi Murai     pfree(bp);
597af57ed9fSAtsushi Murai     return;
598af57ed9fSAtsushi Murai   case ST_CLOSING:
599af57ed9fSAtsushi Murai   case ST_STOPPING:
600af57ed9fSAtsushi Murai     pfree(bp);
601af57ed9fSAtsushi Murai     return;
602af57ed9fSAtsushi Murai   }
603af57ed9fSAtsushi Murai 
60453c9f6c0SAtsushi Murai   (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REJ);
605af57ed9fSAtsushi Murai 
606af57ed9fSAtsushi Murai   switch (fp->state) {
607af57ed9fSAtsushi Murai   case ST_REQSENT:
608af57ed9fSAtsushi Murai   case ST_ACKSENT:
609af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
610af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
611af57ed9fSAtsushi Murai     break;
612af57ed9fSAtsushi Murai   case ST_OPENED:
613af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
614af57ed9fSAtsushi Murai     /* Fall down */
615af57ed9fSAtsushi Murai   case ST_ACKRCVD:
616af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
617af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
618af57ed9fSAtsushi Murai     break;
619af57ed9fSAtsushi Murai   }
620af57ed9fSAtsushi Murai   pfree(bp);
621af57ed9fSAtsushi Murai }
622af57ed9fSAtsushi Murai 
62375240ed1SBrian Somers static void
624944f7098SBrian Somers FsmRecvCodeRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
625af57ed9fSAtsushi Murai {
626cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvCodeRej\n");
627af57ed9fSAtsushi Murai   pfree(bp);
628af57ed9fSAtsushi Murai }
629af57ed9fSAtsushi Murai 
63075240ed1SBrian Somers static void
631944f7098SBrian Somers FsmRecvProtoRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
632af57ed9fSAtsushi Murai {
633af57ed9fSAtsushi Murai   u_short *sp, proto;
634af57ed9fSAtsushi Murai 
635af57ed9fSAtsushi Murai   sp = (u_short *) MBUF_CTOP(bp);
636af57ed9fSAtsushi Murai   proto = ntohs(*sp);
637cb611434SBrian Somers   LogPrintf(fp->LogLevel, "-- Protocol (%04x) was rejected.\n", proto);
638af57ed9fSAtsushi Murai 
639af57ed9fSAtsushi Murai   switch (proto) {
640af57ed9fSAtsushi Murai   case PROTO_LQR:
641af57ed9fSAtsushi Murai     StopLqr(LQM_LQR);
642af57ed9fSAtsushi Murai     break;
643af57ed9fSAtsushi Murai   case PROTO_CCP:
644af57ed9fSAtsushi Murai     fp = &CcpFsm;
645af57ed9fSAtsushi Murai     (fp->LayerFinish) (fp);
646af57ed9fSAtsushi Murai     switch (fp->state) {
647af57ed9fSAtsushi Murai     case ST_CLOSED:
648af57ed9fSAtsushi Murai     case ST_CLOSING:
649af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
650af57ed9fSAtsushi Murai     default:
651af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
652af57ed9fSAtsushi Murai       break;
653af57ed9fSAtsushi Murai     }
654af57ed9fSAtsushi Murai     break;
655af57ed9fSAtsushi Murai   }
656af57ed9fSAtsushi Murai   pfree(bp);
657af57ed9fSAtsushi Murai }
658af57ed9fSAtsushi Murai 
65975240ed1SBrian Somers static void
660944f7098SBrian Somers FsmRecvEchoReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
661af57ed9fSAtsushi Murai {
662af57ed9fSAtsushi Murai   u_char *cp;
663af57ed9fSAtsushi Murai   u_long *lp, magic;
664af57ed9fSAtsushi Murai 
665af57ed9fSAtsushi Murai   cp = MBUF_CTOP(bp);
666af57ed9fSAtsushi Murai   lp = (u_long *) cp;
667af57ed9fSAtsushi Murai   magic = ntohl(*lp);
668af57ed9fSAtsushi Murai   if (magic != LcpInfo.his_magic) {
669927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n");
670af57ed9fSAtsushi Murai     /* XXX: We should send terminate request */
671af57ed9fSAtsushi Murai   }
672af57ed9fSAtsushi Murai   if (fp->state == ST_OPENED) {
673af57ed9fSAtsushi Murai     *lp = htonl(LcpInfo.want_magic);	/* Insert local magic number */
674cb611434SBrian Somers     LogPrintf(fp->LogLevel, "SendEchoRep(%s)\n", StateNames[fp->state]);
675af57ed9fSAtsushi Murai     FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp));
676af57ed9fSAtsushi Murai   }
677af57ed9fSAtsushi Murai   pfree(bp);
678af57ed9fSAtsushi Murai }
679af57ed9fSAtsushi Murai 
68075240ed1SBrian Somers static void
681944f7098SBrian Somers FsmRecvEchoRep(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
682af57ed9fSAtsushi Murai {
683af57ed9fSAtsushi Murai   u_long *lp, magic;
684af57ed9fSAtsushi Murai 
685af57ed9fSAtsushi Murai   lp = (u_long *) MBUF_CTOP(bp);
686af57ed9fSAtsushi Murai   magic = ntohl(*lp);
68785c59f05SJoerg Wunsch /*
68885c59f05SJoerg Wunsch  * Tolerate echo replies with either magic number
68985c59f05SJoerg Wunsch  */
69085c59f05SJoerg Wunsch   if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) {
691927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n",
692af57ed9fSAtsushi Murai 	      LcpInfo.his_magic, magic);
693944f7098SBrian Somers 
694af57ed9fSAtsushi Murai     /*
695944f7098SBrian Somers      * XXX: We should send terminate request. But poor implementation may die
696944f7098SBrian Somers      * as a result.
697af57ed9fSAtsushi Murai      */
698af57ed9fSAtsushi Murai   }
699af57ed9fSAtsushi Murai   RecvEchoLqr(bp);
700af57ed9fSAtsushi Murai   pfree(bp);
701af57ed9fSAtsushi Murai }
702af57ed9fSAtsushi Murai 
70375240ed1SBrian Somers static void
704944f7098SBrian Somers FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
705af57ed9fSAtsushi Murai {
706cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvDiscReq\n");
707af57ed9fSAtsushi Murai   pfree(bp);
708af57ed9fSAtsushi Murai }
709af57ed9fSAtsushi Murai 
71075240ed1SBrian Somers static void
711944f7098SBrian Somers FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
712af57ed9fSAtsushi Murai {
713cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvIdent\n");
714af57ed9fSAtsushi Murai   pfree(bp);
715af57ed9fSAtsushi Murai }
716af57ed9fSAtsushi Murai 
71775240ed1SBrian Somers static void
718944f7098SBrian Somers FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
719af57ed9fSAtsushi Murai {
720cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvTimeRemain\n");
721af57ed9fSAtsushi Murai   pfree(bp);
722af57ed9fSAtsushi Murai }
723af57ed9fSAtsushi Murai 
72475240ed1SBrian Somers static void
725944f7098SBrian Somers FsmRecvResetReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
726af57ed9fSAtsushi Murai {
727cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetReq\n");
728af57ed9fSAtsushi Murai   CcpRecvResetReq(fp);
729cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendResetAck\n");
730af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0);
731af57ed9fSAtsushi Murai   pfree(bp);
732af57ed9fSAtsushi Murai }
733af57ed9fSAtsushi Murai 
73475240ed1SBrian Somers static void
735944f7098SBrian Somers FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
736af57ed9fSAtsushi Murai {
737cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetAck\n");
73829a6597cSBrian Somers   Pred1Init(1);			/* Initialize Input part */
739af57ed9fSAtsushi Murai   fp->reqid++;
740af57ed9fSAtsushi Murai   pfree(bp);
741af57ed9fSAtsushi Murai }
742af57ed9fSAtsushi Murai 
743af57ed9fSAtsushi Murai struct fsmcodedesc FsmCodes[] = {
744af57ed9fSAtsushi Murai   {FsmRecvConfigReq, "Configure Request",},
745af57ed9fSAtsushi Murai   {FsmRecvConfigAck, "Configure Ack",},
746af57ed9fSAtsushi Murai   {FsmRecvConfigNak, "Configure Nak",},
747af57ed9fSAtsushi Murai   {FsmRecvConfigRej, "Configure Reject",},
748af57ed9fSAtsushi Murai   {FsmRecvTermReq, "Terminate Request",},
749af57ed9fSAtsushi Murai   {FsmRecvTermAck, "Terminate Ack",},
750af57ed9fSAtsushi Murai   {FsmRecvCodeRej, "Code Reject",},
751af57ed9fSAtsushi Murai   {FsmRecvProtoRej, "Protocol Reject",},
752af57ed9fSAtsushi Murai   {FsmRecvEchoReq, "Echo Request",},
753af57ed9fSAtsushi Murai   {FsmRecvEchoRep, "Echo Reply",},
754af57ed9fSAtsushi Murai   {FsmRecvDiscReq, "Discard Request",},
755af57ed9fSAtsushi Murai   {FsmRecvIdent, "Ident",},
756af57ed9fSAtsushi Murai   {FsmRecvTimeRemain, "Time Remain",},
757af57ed9fSAtsushi Murai   {FsmRecvResetReq, "Reset Request",},
758af57ed9fSAtsushi Murai   {FsmRecvResetAck, "Reset Ack",},
759af57ed9fSAtsushi Murai };
760af57ed9fSAtsushi Murai 
761af57ed9fSAtsushi Murai void
762944f7098SBrian Somers FsmInput(struct fsm * fp, struct mbuf * bp)
763af57ed9fSAtsushi Murai {
764af57ed9fSAtsushi Murai   int len;
765af57ed9fSAtsushi Murai   struct fsmheader *lhp;
766af57ed9fSAtsushi Murai   struct fsmcodedesc *codep;
767af57ed9fSAtsushi Murai 
768af57ed9fSAtsushi Murai   len = plength(bp);
769af57ed9fSAtsushi Murai   if (len < sizeof(struct fsmheader)) {
770af57ed9fSAtsushi Murai     pfree(bp);
771af57ed9fSAtsushi Murai     return;
772af57ed9fSAtsushi Murai   }
773af57ed9fSAtsushi Murai   lhp = (struct fsmheader *) MBUF_CTOP(bp);
774af57ed9fSAtsushi Murai   if (lhp->code == 0 || lhp->code > fp->max_code) {
775af57ed9fSAtsushi Murai     pfree(bp);			/* XXX: Should send code reject */
776af57ed9fSAtsushi Murai     return;
777af57ed9fSAtsushi Murai   }
778af57ed9fSAtsushi Murai   bp->offset += sizeof(struct fsmheader);
779af57ed9fSAtsushi Murai   bp->cnt -= sizeof(struct fsmheader);
780af57ed9fSAtsushi Murai 
781af57ed9fSAtsushi Murai   codep = FsmCodes + lhp->code - 1;
782cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n",
783927145beSBrian Somers 	    codep->name, lhp->id, StateNames[fp->state], fp->state);
784927145beSBrian Somers   if (LogIsKept(LogDEBUG))
785af57ed9fSAtsushi Murai     LogMemory();
786af57ed9fSAtsushi Murai   (codep->action) (fp, lhp, bp);
787927145beSBrian Somers   if (LogIsKept(LogDEBUG))
788af57ed9fSAtsushi Murai     LogMemory();
789af57ed9fSAtsushi Murai }
790