xref: /freebsd/usr.sbin/ppp/fsm.c (revision 98baf7c8fd21472c4a5b0871ff095d95c017c85d)
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  *
2098baf7c8SBrian Somers  * $Id: fsm.c,v 1.25 1997/12/24 09:28:58 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"
47af57ed9fSAtsushi Murai 
4875240ed1SBrian Somers u_char AckBuff[200];
4975240ed1SBrian Somers u_char NakBuff[200];
5075240ed1SBrian Somers u_char RejBuff[100];
5175240ed1SBrian Somers u_char ReqBuff[200];
5275240ed1SBrian Somers u_char *ackp = NULL;
5375240ed1SBrian Somers u_char *nakp = NULL;
5475240ed1SBrian Somers u_char *rejp = NULL;
5575240ed1SBrian Somers 
5675240ed1SBrian Somers static void FsmSendConfigReq(struct fsm *);
5775240ed1SBrian Somers static void FsmSendTerminateReq(struct fsm *);
5875240ed1SBrian Somers static void FsmInitRestartCounter(struct fsm *);
59af57ed9fSAtsushi Murai 
60ed6a16c1SPoul-Henning Kamp char const *StateNames[] = {
61af57ed9fSAtsushi Murai   "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
62927145beSBrian Somers   "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
63af57ed9fSAtsushi Murai };
64af57ed9fSAtsushi Murai 
6571144dc5SBrian Somers static void
66b6e82f33SBrian Somers StoppedTimeout(void *v)
6771144dc5SBrian Somers {
68b6e82f33SBrian Somers   struct fsm *fp = (struct fsm *)v;
69b6e82f33SBrian Somers 
70cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Stopped timer expired\n");
7171144dc5SBrian Somers   if (modem != -1)
7271144dc5SBrian Somers     DownConnection();
7371144dc5SBrian Somers   else
7471144dc5SBrian Somers     FsmDown(fp);
7571144dc5SBrian Somers }
7671144dc5SBrian Somers 
77af57ed9fSAtsushi Murai void
78944f7098SBrian Somers FsmInit(struct fsm * fp)
79af57ed9fSAtsushi Murai {
80927145beSBrian Somers   LogPrintf(LogDEBUG, "FsmInit\n");
81af57ed9fSAtsushi Murai   fp->state = ST_INITIAL;
82af57ed9fSAtsushi Murai   fp->reqid = 1;
83af57ed9fSAtsushi Murai   fp->restart = 1;
84af57ed9fSAtsushi Murai   fp->maxconfig = 3;
85af57ed9fSAtsushi Murai }
86af57ed9fSAtsushi Murai 
8775240ed1SBrian Somers static void
88944f7098SBrian Somers NewState(struct fsm * fp, int new)
89af57ed9fSAtsushi Murai {
90cb611434SBrian Somers   LogPrintf(fp->LogLevel, "State change %s --> %s\n",
91927145beSBrian Somers 	    StateNames[fp->state], StateNames[new]);
92cb611434SBrian Somers   if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
93cb611434SBrian Somers     StopTimer(&fp->StoppedTimer);
94af57ed9fSAtsushi Murai   fp->state = new;
9571144dc5SBrian Somers   if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
96af57ed9fSAtsushi Murai     StopTimer(&fp->FsmTimer);
97cb611434SBrian Somers     if (new == ST_STOPPED && fp->StoppedTimer.load) {
98cb611434SBrian Somers       fp->StoppedTimer.state = TIMER_STOPPED;
99cb611434SBrian Somers       fp->StoppedTimer.func = StoppedTimeout;
100cb611434SBrian Somers       fp->StoppedTimer.arg = (void *) fp;
101cb611434SBrian Somers       StartTimer(&fp->StoppedTimer);
10271144dc5SBrian Somers     }
10371144dc5SBrian Somers   }
104af57ed9fSAtsushi Murai }
105af57ed9fSAtsushi Murai 
106af57ed9fSAtsushi Murai void
107944f7098SBrian Somers FsmOutput(struct fsm * fp, u_int code, u_int id, u_char * ptr, int count)
108af57ed9fSAtsushi Murai {
109af57ed9fSAtsushi Murai   int plen;
110af57ed9fSAtsushi Murai   struct fsmheader lh;
111af57ed9fSAtsushi Murai   struct mbuf *bp;
112af57ed9fSAtsushi Murai 
113af57ed9fSAtsushi Murai   plen = sizeof(struct fsmheader) + count;
114af57ed9fSAtsushi Murai   lh.code = code;
115af57ed9fSAtsushi Murai   lh.id = id;
116af57ed9fSAtsushi Murai   lh.length = htons(plen);
117af57ed9fSAtsushi Murai   bp = mballoc(plen, MB_FSM);
11875240ed1SBrian Somers   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
119af57ed9fSAtsushi Murai   if (count)
12075240ed1SBrian Somers     memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
121927145beSBrian Somers   LogDumpBp(LogDEBUG, "FsmOutput", bp);
12276bd0c0aSDoug Rabson   HdlcOutput(PRI_LINK, fp->proto, bp);
123af57ed9fSAtsushi Murai }
124af57ed9fSAtsushi Murai 
125af57ed9fSAtsushi Murai void
126944f7098SBrian Somers FsmOpen(struct fsm * fp)
127af57ed9fSAtsushi Murai {
128af57ed9fSAtsushi Murai   switch (fp->state) {
129af57ed9fSAtsushi Murai     case ST_INITIAL:
130af57ed9fSAtsushi Murai     (fp->LayerStart) (fp);
131af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
132af57ed9fSAtsushi Murai     break;
133af57ed9fSAtsushi Murai   case ST_STARTING:
134af57ed9fSAtsushi Murai     break;
135af57ed9fSAtsushi Murai   case ST_CLOSED:
136af57ed9fSAtsushi Murai     if (fp->open_mode == OPEN_PASSIVE) {
137af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
138af57ed9fSAtsushi Murai     } else {
139af57ed9fSAtsushi Murai       FsmInitRestartCounter(fp);
140af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
141af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
142af57ed9fSAtsushi Murai     }
143af57ed9fSAtsushi Murai     break;
144af57ed9fSAtsushi Murai   case ST_STOPPED:		/* XXX: restart option */
145af57ed9fSAtsushi Murai   case ST_REQSENT:
146af57ed9fSAtsushi Murai   case ST_ACKRCVD:
147af57ed9fSAtsushi Murai   case ST_ACKSENT:
148af57ed9fSAtsushi Murai   case ST_OPENED:		/* XXX: restart option */
149af57ed9fSAtsushi Murai     break;
150af57ed9fSAtsushi Murai   case ST_CLOSING:		/* XXX: restart option */
151af57ed9fSAtsushi Murai   case ST_STOPPING:		/* XXX: restart option */
152af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPING);
153af57ed9fSAtsushi Murai     break;
154af57ed9fSAtsushi Murai   }
155af57ed9fSAtsushi Murai }
156af57ed9fSAtsushi Murai 
157af57ed9fSAtsushi Murai void
158944f7098SBrian Somers FsmUp(struct fsm * fp)
159af57ed9fSAtsushi Murai {
160af57ed9fSAtsushi Murai   switch (fp->state) {
161af57ed9fSAtsushi Murai     case ST_INITIAL:
162af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
163af57ed9fSAtsushi Murai     break;
164af57ed9fSAtsushi Murai   case ST_STARTING:
165af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
166af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
167af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
168af57ed9fSAtsushi Murai     break;
169af57ed9fSAtsushi Murai   default:
170cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]);
171af57ed9fSAtsushi Murai     break;
172af57ed9fSAtsushi Murai   }
173af57ed9fSAtsushi Murai }
174af57ed9fSAtsushi Murai 
175af57ed9fSAtsushi Murai void
176944f7098SBrian Somers FsmDown(struct fsm * fp)
177af57ed9fSAtsushi Murai {
178af57ed9fSAtsushi Murai   switch (fp->state) {
179af57ed9fSAtsushi Murai     case ST_CLOSED:
180af57ed9fSAtsushi Murai     case ST_CLOSING:
181af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
182af57ed9fSAtsushi Murai     break;
183af57ed9fSAtsushi Murai   case ST_STOPPED:
184af57ed9fSAtsushi Murai     (fp->LayerStart) (fp);
185af57ed9fSAtsushi Murai     /* Fall into.. */
186af57ed9fSAtsushi Murai   case ST_STOPPING:
187af57ed9fSAtsushi Murai   case ST_REQSENT:
188af57ed9fSAtsushi Murai   case ST_ACKRCVD:
189af57ed9fSAtsushi Murai   case ST_ACKSENT:
190af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
191af57ed9fSAtsushi Murai     break;
192af57ed9fSAtsushi Murai   case ST_OPENED:
193af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
194af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
195af57ed9fSAtsushi Murai     break;
196af57ed9fSAtsushi Murai   }
197af57ed9fSAtsushi Murai }
198af57ed9fSAtsushi Murai 
199af57ed9fSAtsushi Murai void
200944f7098SBrian Somers FsmClose(struct fsm * fp)
201af57ed9fSAtsushi Murai {
202af57ed9fSAtsushi Murai   switch (fp->state) {
203af57ed9fSAtsushi Murai     case ST_STARTING:
204af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
205af57ed9fSAtsushi Murai     break;
206af57ed9fSAtsushi Murai   case ST_STOPPED:
207af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
208af57ed9fSAtsushi Murai     break;
209af57ed9fSAtsushi Murai   case ST_STOPPING:
210af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
211af57ed9fSAtsushi Murai     break;
212af57ed9fSAtsushi Murai   case ST_OPENED:
213af57ed9fSAtsushi Murai     (fp->LayerDown) (fp);
214af57ed9fSAtsushi Murai     /* Fall down */
215af57ed9fSAtsushi Murai   case ST_REQSENT:
216af57ed9fSAtsushi Murai   case ST_ACKRCVD:
217af57ed9fSAtsushi Murai   case ST_ACKSENT:
218af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
219af57ed9fSAtsushi Murai     FsmSendTerminateReq(fp);
220af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
221af57ed9fSAtsushi Murai     break;
222af57ed9fSAtsushi Murai   }
223af57ed9fSAtsushi Murai }
224af57ed9fSAtsushi Murai 
225af57ed9fSAtsushi Murai /*
226af57ed9fSAtsushi Murai  *	Send functions
227af57ed9fSAtsushi Murai  */
22875240ed1SBrian Somers static void
229944f7098SBrian Somers FsmSendConfigReq(struct fsm * fp)
230af57ed9fSAtsushi Murai {
231af57ed9fSAtsushi Murai   if (--fp->maxconfig > 0) {
232af57ed9fSAtsushi Murai     (fp->SendConfigReq) (fp);
233af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);	/* Start restart timer */
234af57ed9fSAtsushi Murai     fp->restart--;		/* Decrement restart counter */
235af57ed9fSAtsushi Murai   } else {
236af57ed9fSAtsushi Murai     FsmClose(fp);
237af57ed9fSAtsushi Murai   }
238af57ed9fSAtsushi Murai }
239af57ed9fSAtsushi Murai 
24075240ed1SBrian Somers static void
241944f7098SBrian Somers FsmSendTerminateReq(struct fsm * fp)
242af57ed9fSAtsushi Murai {
243cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendTerminateReq.\n");
244af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
245af57ed9fSAtsushi Murai   (fp->SendTerminateReq) (fp);
246af57ed9fSAtsushi Murai   StartTimer(&fp->FsmTimer);	/* Start restart timer */
247af57ed9fSAtsushi Murai   fp->restart--;		/* Decrement restart counter */
248af57ed9fSAtsushi Murai }
249af57ed9fSAtsushi Murai 
250af57ed9fSAtsushi Murai static void
251944f7098SBrian Somers FsmSendConfigAck(struct fsm * fp,
252944f7098SBrian Somers 		 struct fsmheader * lhp,
253944f7098SBrian Somers 		 u_char * option,
254944f7098SBrian Somers 		 int count)
255af57ed9fSAtsushi Murai {
256cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]);
25753c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
258af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
259af57ed9fSAtsushi Murai }
260af57ed9fSAtsushi Murai 
261af57ed9fSAtsushi Murai static void
262944f7098SBrian Somers FsmSendConfigRej(struct fsm * fp,
263944f7098SBrian Somers 		 struct fsmheader * lhp,
264944f7098SBrian Somers 		 u_char * option,
265944f7098SBrian Somers 		 int count)
266af57ed9fSAtsushi Murai {
267cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]);
26853c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
269af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
270af57ed9fSAtsushi Murai }
271af57ed9fSAtsushi Murai 
272af57ed9fSAtsushi Murai static void
273944f7098SBrian Somers FsmSendConfigNak(struct fsm * fp,
274944f7098SBrian Somers 		 struct fsmheader * lhp,
275944f7098SBrian Somers 		 u_char * option,
276944f7098SBrian Somers 		 int count)
277af57ed9fSAtsushi Murai {
278cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]);
27953c9f6c0SAtsushi Murai   (fp->DecodeConfig) (option, count, MODE_NOP);
280af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
281af57ed9fSAtsushi Murai }
282af57ed9fSAtsushi Murai 
283af57ed9fSAtsushi Murai /*
284af57ed9fSAtsushi Murai  *	Timeout actions
285af57ed9fSAtsushi Murai  */
28675240ed1SBrian Somers static void
287b6e82f33SBrian Somers FsmTimeout(void *v)
288af57ed9fSAtsushi Murai {
289b6e82f33SBrian Somers   struct fsm *fp = (struct fsm *)v;
290b6e82f33SBrian Somers 
291af57ed9fSAtsushi Murai   if (fp->restart) {
292af57ed9fSAtsushi Murai     switch (fp->state) {
293af57ed9fSAtsushi Murai       case ST_CLOSING:
294af57ed9fSAtsushi Murai       case ST_STOPPING:
295af57ed9fSAtsushi Murai       FsmSendTerminateReq(fp);
296af57ed9fSAtsushi Murai       break;
297af57ed9fSAtsushi Murai     case ST_REQSENT:
298af57ed9fSAtsushi Murai     case ST_ACKSENT:
299af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
300af57ed9fSAtsushi Murai       break;
301af57ed9fSAtsushi Murai     case ST_ACKRCVD:
302af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
303af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
304af57ed9fSAtsushi Murai       break;
305af57ed9fSAtsushi Murai     }
306af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);
307af57ed9fSAtsushi Murai   } else {
308af57ed9fSAtsushi Murai     switch (fp->state) {
309af57ed9fSAtsushi Murai     case ST_CLOSING:
310af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
311af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
312af57ed9fSAtsushi Murai       break;
313af57ed9fSAtsushi Murai     case ST_STOPPING:
314af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
315af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
316af57ed9fSAtsushi Murai       break;
317af57ed9fSAtsushi Murai     case ST_REQSENT:		/* XXX: 3p */
318af57ed9fSAtsushi Murai     case ST_ACKSENT:
319af57ed9fSAtsushi Murai     case ST_ACKRCVD:
320af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
321af57ed9fSAtsushi Murai       (fp->LayerFinish) (fp);
322af57ed9fSAtsushi Murai       break;
323af57ed9fSAtsushi Murai     }
324af57ed9fSAtsushi Murai   }
325af57ed9fSAtsushi Murai }
326af57ed9fSAtsushi Murai 
32775240ed1SBrian Somers static void
328944f7098SBrian Somers FsmInitRestartCounter(struct fsm * fp)
329af57ed9fSAtsushi Murai {
330af57ed9fSAtsushi Murai   StopTimer(&fp->FsmTimer);
331af57ed9fSAtsushi Murai   fp->FsmTimer.state = TIMER_STOPPED;
332af57ed9fSAtsushi Murai   fp->FsmTimer.func = FsmTimeout;
333af57ed9fSAtsushi Murai   fp->FsmTimer.arg = (void *) fp;
334af57ed9fSAtsushi Murai   (fp->InitRestartCounter) (fp);
335af57ed9fSAtsushi Murai }
336af57ed9fSAtsushi Murai 
337af57ed9fSAtsushi Murai /*
338af57ed9fSAtsushi Murai  *   Actions when receive packets
339af57ed9fSAtsushi Murai  */
34075240ed1SBrian Somers static void
341944f7098SBrian Somers FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
342944f7098SBrian Somers /* RCR */
343af57ed9fSAtsushi Murai {
34453c9f6c0SAtsushi Murai   int plen, flen;
345af57ed9fSAtsushi Murai   int ackaction = 0;
346af57ed9fSAtsushi Murai 
347af57ed9fSAtsushi Murai   plen = plength(bp);
34870ee81ffSBrian Somers   flen = ntohs(lhp->length) - sizeof *lhp;
34953c9f6c0SAtsushi Murai   if (plen < flen) {
350afc7fa2cSBrian Somers     LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)\n",
351afc7fa2cSBrian Somers 	      plen, flen);
352af57ed9fSAtsushi Murai     pfree(bp);
353af57ed9fSAtsushi Murai     return;
354af57ed9fSAtsushi Murai   }
355af57ed9fSAtsushi Murai 
356af57ed9fSAtsushi Murai   /*
357af57ed9fSAtsushi Murai    * Check and process easy case
358af57ed9fSAtsushi Murai    */
359af57ed9fSAtsushi Murai   switch (fp->state) {
360af57ed9fSAtsushi Murai   case ST_INITIAL:
361af57ed9fSAtsushi Murai   case ST_STARTING:
362cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]);
363af57ed9fSAtsushi Murai     pfree(bp);
364af57ed9fSAtsushi Murai     return;
365af57ed9fSAtsushi Murai   case ST_CLOSED:
366af57ed9fSAtsushi Murai     (fp->SendTerminateAck) (fp);
367af57ed9fSAtsushi Murai     pfree(bp);
368af57ed9fSAtsushi Murai     return;
369af57ed9fSAtsushi Murai   case ST_CLOSING:
370bcc332bdSBrian Somers     LogPrintf(fp->LogLevel, "Error: Got ConfigReq while state = %d\n",
371bcc332bdSBrian Somers               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);
46770ee81ffSBrian Somers   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);
57770ee81ffSBrian Somers   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 {
72798baf7c8SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetReq(%d)\n", lhp->id);
728af57ed9fSAtsushi Murai   CcpRecvResetReq(fp);
72998baf7c8SBrian Somers   /*
73098baf7c8SBrian Somers    * All sendable compressed packets are queued in the PRI_NORMAL modem
73198baf7c8SBrian Somers    * output queue.... dump 'em to the priority queue so that they arrive
73298baf7c8SBrian Somers    * at the peer before our ResetAck.
73398baf7c8SBrian Somers    */
73498baf7c8SBrian Somers   SequenceQueues();
73598baf7c8SBrian Somers   LogPrintf(fp->LogLevel, "SendResetAck(%d)\n", lhp->id);
73698baf7c8SBrian Somers   FsmOutput(fp, CODE_RESETACK, lhp->id, NULL, 0);
737af57ed9fSAtsushi Murai   pfree(bp);
738af57ed9fSAtsushi Murai }
739af57ed9fSAtsushi Murai 
74075240ed1SBrian Somers static void
741944f7098SBrian Somers FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
742af57ed9fSAtsushi Murai {
74398baf7c8SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetAck(%d)\n", lhp->id);
74498baf7c8SBrian Somers   CcpResetInput(lhp->id);
745af57ed9fSAtsushi Murai   fp->reqid++;
746af57ed9fSAtsushi Murai   pfree(bp);
747af57ed9fSAtsushi Murai }
748af57ed9fSAtsushi Murai 
7490053cc58SBrian Somers static const struct fsmcodedesc FsmCodes[] = {
750af57ed9fSAtsushi Murai   {FsmRecvConfigReq, "Configure Request",},
751af57ed9fSAtsushi Murai   {FsmRecvConfigAck, "Configure Ack",},
752af57ed9fSAtsushi Murai   {FsmRecvConfigNak, "Configure Nak",},
753af57ed9fSAtsushi Murai   {FsmRecvConfigRej, "Configure Reject",},
754af57ed9fSAtsushi Murai   {FsmRecvTermReq, "Terminate Request",},
755af57ed9fSAtsushi Murai   {FsmRecvTermAck, "Terminate Ack",},
756af57ed9fSAtsushi Murai   {FsmRecvCodeRej, "Code Reject",},
757af57ed9fSAtsushi Murai   {FsmRecvProtoRej, "Protocol Reject",},
758af57ed9fSAtsushi Murai   {FsmRecvEchoReq, "Echo Request",},
759af57ed9fSAtsushi Murai   {FsmRecvEchoRep, "Echo Reply",},
760af57ed9fSAtsushi Murai   {FsmRecvDiscReq, "Discard Request",},
761af57ed9fSAtsushi Murai   {FsmRecvIdent, "Ident",},
762af57ed9fSAtsushi Murai   {FsmRecvTimeRemain, "Time Remain",},
763af57ed9fSAtsushi Murai   {FsmRecvResetReq, "Reset Request",},
764af57ed9fSAtsushi Murai   {FsmRecvResetAck, "Reset Ack",},
765af57ed9fSAtsushi Murai };
766af57ed9fSAtsushi Murai 
767af57ed9fSAtsushi Murai void
768944f7098SBrian Somers FsmInput(struct fsm * fp, struct mbuf * bp)
769af57ed9fSAtsushi Murai {
770af57ed9fSAtsushi Murai   int len;
771af57ed9fSAtsushi Murai   struct fsmheader *lhp;
7720053cc58SBrian Somers   const struct fsmcodedesc *codep;
773af57ed9fSAtsushi Murai 
774af57ed9fSAtsushi Murai   len = plength(bp);
775af57ed9fSAtsushi Murai   if (len < sizeof(struct fsmheader)) {
776af57ed9fSAtsushi Murai     pfree(bp);
777af57ed9fSAtsushi Murai     return;
778af57ed9fSAtsushi Murai   }
779af57ed9fSAtsushi Murai   lhp = (struct fsmheader *) MBUF_CTOP(bp);
780af57ed9fSAtsushi Murai   if (lhp->code == 0 || lhp->code > fp->max_code) {
781af57ed9fSAtsushi Murai     pfree(bp);			/* XXX: Should send code reject */
782af57ed9fSAtsushi Murai     return;
783af57ed9fSAtsushi Murai   }
784af57ed9fSAtsushi Murai   bp->offset += sizeof(struct fsmheader);
785af57ed9fSAtsushi Murai   bp->cnt -= sizeof(struct fsmheader);
786af57ed9fSAtsushi Murai 
787af57ed9fSAtsushi Murai   codep = FsmCodes + lhp->code - 1;
788cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n",
789927145beSBrian Somers 	    codep->name, lhp->id, StateNames[fp->state], fp->state);
790927145beSBrian Somers   if (LogIsKept(LogDEBUG))
791af57ed9fSAtsushi Murai     LogMemory();
792af57ed9fSAtsushi Murai   (codep->action) (fp, lhp, bp);
793927145beSBrian Somers   if (LogIsKept(LogDEBUG))
794af57ed9fSAtsushi Murai     LogMemory();
795af57ed9fSAtsushi Murai }
796