xref: /freebsd/usr.sbin/ppp/fsm.c (revision cb611434af6db6982dbe30dadd191016039b00be)
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  *
20cb611434SBrian Somers  * $Id: fsm.c,v 1.14 1997/08/17 20:45:46 brian Exp $
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *  TODO:
23af57ed9fSAtsushi Murai  *		o Refer loglevel for log output
24af57ed9fSAtsushi Murai  *		o Better option log display
25af57ed9fSAtsushi Murai  */
26af57ed9fSAtsushi Murai #include "fsm.h"
27af57ed9fSAtsushi Murai #include "hdlc.h"
28af57ed9fSAtsushi Murai #include "lqr.h"
29af57ed9fSAtsushi Murai #include "lcpproto.h"
30af57ed9fSAtsushi Murai #include "lcp.h"
31ed6a16c1SPoul-Henning Kamp #include "ccp.h"
3271144dc5SBrian Somers #include "modem.h"
3371144dc5SBrian Somers #include "loadalias.h"
3471144dc5SBrian Somers #include "vars.h"
35af57ed9fSAtsushi Murai 
36af57ed9fSAtsushi Murai void FsmSendConfigReq(struct fsm *fp);
37af57ed9fSAtsushi Murai void FsmSendTerminateReq(struct fsm *fp);
38af57ed9fSAtsushi Murai void FsmInitRestartCounter(struct fsm *fp);
39af57ed9fSAtsushi Murai void FsmTimeout(struct fsm *fp);
40af57ed9fSAtsushi Murai 
41ed6a16c1SPoul-Henning Kamp char const *StateNames[] = {
42af57ed9fSAtsushi Murai   "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
43927145beSBrian Somers   "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
44af57ed9fSAtsushi Murai };
45af57ed9fSAtsushi Murai 
4671144dc5SBrian Somers static void
4771144dc5SBrian Somers StoppedTimeout(fp)
4871144dc5SBrian Somers struct fsm *fp;
4971144dc5SBrian Somers {
50cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Stopped timer expired\n");
5171144dc5SBrian Somers   if (modem != -1)
5271144dc5SBrian Somers     DownConnection();
5371144dc5SBrian Somers   else
5471144dc5SBrian Somers     FsmDown(fp);
5571144dc5SBrian Somers }
5671144dc5SBrian Somers 
57af57ed9fSAtsushi Murai void
58af57ed9fSAtsushi Murai FsmInit(fp)
59af57ed9fSAtsushi Murai struct fsm *fp;
60af57ed9fSAtsushi Murai {
61927145beSBrian Somers   LogPrintf(LogDEBUG, "FsmInit\n");
62af57ed9fSAtsushi Murai   fp->state = ST_INITIAL;
63af57ed9fSAtsushi Murai   fp->reqid = 1;
64af57ed9fSAtsushi Murai   fp->restart = 1;
65af57ed9fSAtsushi Murai   fp->maxconfig = 3;
66af57ed9fSAtsushi Murai }
67af57ed9fSAtsushi Murai 
68af57ed9fSAtsushi Murai void
69af57ed9fSAtsushi Murai NewState(fp, new)
70af57ed9fSAtsushi Murai struct fsm *fp;
71af57ed9fSAtsushi Murai int new;
72af57ed9fSAtsushi Murai {
73cb611434SBrian Somers   LogPrintf(fp->LogLevel, "State change %s --> %s\n",
74927145beSBrian Somers 	  StateNames[fp->state], StateNames[new]);
75cb611434SBrian Somers   if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
76cb611434SBrian Somers       StopTimer(&fp->StoppedTimer);
77af57ed9fSAtsushi Murai   fp->state = new;
7871144dc5SBrian Somers   if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
79af57ed9fSAtsushi Murai     StopTimer(&fp->FsmTimer);
80cb611434SBrian Somers     if (new == ST_STOPPED && fp->StoppedTimer.load) {
81cb611434SBrian Somers       fp->StoppedTimer.state = TIMER_STOPPED;
82cb611434SBrian Somers       fp->StoppedTimer.func = StoppedTimeout;
83cb611434SBrian Somers       fp->StoppedTimer.arg = (void *)fp;
84cb611434SBrian Somers       StartTimer(&fp->StoppedTimer);
8571144dc5SBrian Somers     }
8671144dc5SBrian Somers   }
87af57ed9fSAtsushi Murai }
88af57ed9fSAtsushi Murai 
89af57ed9fSAtsushi Murai void
90af57ed9fSAtsushi Murai FsmOutput(fp, code, id, ptr, count)
91af57ed9fSAtsushi Murai struct fsm *fp;
92af57ed9fSAtsushi Murai u_int code, id;
93af57ed9fSAtsushi Murai u_char *ptr;
94af57ed9fSAtsushi Murai int count;
95af57ed9fSAtsushi Murai {
96af57ed9fSAtsushi Murai   int plen;
97af57ed9fSAtsushi Murai   struct fsmheader lh;
98af57ed9fSAtsushi Murai   struct mbuf *bp;
99af57ed9fSAtsushi Murai 
100af57ed9fSAtsushi Murai   plen =  sizeof(struct fsmheader) + count;
101af57ed9fSAtsushi Murai   lh.code = code;
102af57ed9fSAtsushi Murai   lh.id = id;
103af57ed9fSAtsushi Murai   lh.length = htons(plen);
104af57ed9fSAtsushi Murai   bp = mballoc(plen, MB_FSM);
105af57ed9fSAtsushi Murai   bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader));
106af57ed9fSAtsushi Murai   if (count)
107af57ed9fSAtsushi Murai     bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count);
108927145beSBrian Somers   LogDumpBp(LogDEBUG, "FsmOutput", bp);
10976bd0c0aSDoug Rabson   HdlcOutput(PRI_LINK, fp->proto, bp);
110af57ed9fSAtsushi Murai }
111af57ed9fSAtsushi Murai 
112af57ed9fSAtsushi Murai void
113af57ed9fSAtsushi Murai FsmOpen(fp)
114af57ed9fSAtsushi Murai struct fsm *fp;
115af57ed9fSAtsushi Murai {
116af57ed9fSAtsushi Murai   switch (fp->state) {
117af57ed9fSAtsushi Murai   case ST_INITIAL:
118af57ed9fSAtsushi Murai     (fp->LayerStart)(fp);
119af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
120af57ed9fSAtsushi Murai     break;
121af57ed9fSAtsushi Murai   case ST_STARTING:
122af57ed9fSAtsushi Murai     break;
123af57ed9fSAtsushi Murai   case ST_CLOSED:
124af57ed9fSAtsushi Murai     if (fp->open_mode == OPEN_PASSIVE) {
125af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
126af57ed9fSAtsushi Murai     } else {
127af57ed9fSAtsushi Murai       FsmInitRestartCounter(fp);
128af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
129af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
130af57ed9fSAtsushi Murai     }
131af57ed9fSAtsushi Murai     break;
132af57ed9fSAtsushi Murai   case ST_STOPPED:	/* XXX: restart option */
133af57ed9fSAtsushi Murai   case ST_REQSENT:
134af57ed9fSAtsushi Murai   case ST_ACKRCVD:
135af57ed9fSAtsushi Murai   case ST_ACKSENT:
136af57ed9fSAtsushi Murai   case ST_OPENED:	/* XXX: restart option */
137af57ed9fSAtsushi Murai     break;
138af57ed9fSAtsushi Murai   case ST_CLOSING:	/* XXX: restart option */
139af57ed9fSAtsushi Murai   case ST_STOPPING:	/* XXX: restart option */
140af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPING);
141af57ed9fSAtsushi Murai     break;
142af57ed9fSAtsushi Murai   }
143af57ed9fSAtsushi Murai }
144af57ed9fSAtsushi Murai 
145af57ed9fSAtsushi Murai void
146af57ed9fSAtsushi Murai FsmUp(fp)
147af57ed9fSAtsushi Murai struct fsm *fp;
148af57ed9fSAtsushi Murai {
149af57ed9fSAtsushi Murai   switch (fp->state) {
150af57ed9fSAtsushi Murai   case ST_INITIAL:
151af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
152af57ed9fSAtsushi Murai     break;
153af57ed9fSAtsushi Murai   case ST_STARTING:
154af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
155af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
156af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
157af57ed9fSAtsushi Murai     break;
158af57ed9fSAtsushi Murai   default:
159cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]);
160af57ed9fSAtsushi Murai     break;
161af57ed9fSAtsushi Murai   }
162af57ed9fSAtsushi Murai }
163af57ed9fSAtsushi Murai 
164af57ed9fSAtsushi Murai void
165af57ed9fSAtsushi Murai FsmDown(fp)
166af57ed9fSAtsushi Murai struct fsm *fp;
167af57ed9fSAtsushi Murai {
168af57ed9fSAtsushi Murai   switch (fp->state) {
169af57ed9fSAtsushi Murai   case ST_CLOSED:
170af57ed9fSAtsushi Murai   case ST_CLOSING:
171af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
172af57ed9fSAtsushi Murai     break;
173af57ed9fSAtsushi Murai   case ST_STOPPED:
174af57ed9fSAtsushi Murai     (fp->LayerStart)(fp);
175af57ed9fSAtsushi Murai     /* Fall into.. */
176af57ed9fSAtsushi Murai   case ST_STOPPING:
177af57ed9fSAtsushi Murai   case ST_REQSENT:
178af57ed9fSAtsushi Murai   case ST_ACKRCVD:
179af57ed9fSAtsushi Murai   case ST_ACKSENT:
180af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
181af57ed9fSAtsushi Murai     break;
182af57ed9fSAtsushi Murai   case ST_OPENED:
183af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
184af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
185af57ed9fSAtsushi Murai     break;
186af57ed9fSAtsushi Murai   }
187af57ed9fSAtsushi Murai }
188af57ed9fSAtsushi Murai 
189af57ed9fSAtsushi Murai void
190af57ed9fSAtsushi Murai FsmClose(fp)
191af57ed9fSAtsushi Murai struct fsm *fp;
192af57ed9fSAtsushi Murai {
193af57ed9fSAtsushi Murai   switch (fp->state) {
194af57ed9fSAtsushi Murai   case ST_STARTING:
195af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
196af57ed9fSAtsushi Murai     break;
197af57ed9fSAtsushi Murai   case ST_STOPPED:
198af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
199af57ed9fSAtsushi Murai     break;
200af57ed9fSAtsushi Murai   case ST_STOPPING:
201af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
202af57ed9fSAtsushi Murai     break;
203af57ed9fSAtsushi Murai   case ST_OPENED:
204af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
205af57ed9fSAtsushi Murai     /* Fall down */
206af57ed9fSAtsushi Murai   case ST_REQSENT:
207af57ed9fSAtsushi Murai   case ST_ACKRCVD:
208af57ed9fSAtsushi Murai   case ST_ACKSENT:
209af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
210af57ed9fSAtsushi Murai     FsmSendTerminateReq(fp);
211af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
212af57ed9fSAtsushi Murai     break;
213af57ed9fSAtsushi Murai   }
214af57ed9fSAtsushi Murai }
215af57ed9fSAtsushi Murai 
216af57ed9fSAtsushi Murai /*
217af57ed9fSAtsushi Murai  *	Send functions
218af57ed9fSAtsushi Murai  */
219af57ed9fSAtsushi Murai void
220af57ed9fSAtsushi Murai FsmSendConfigReq(fp)
221af57ed9fSAtsushi Murai struct fsm *fp;
222af57ed9fSAtsushi Murai {
223af57ed9fSAtsushi Murai   if (--fp->maxconfig > 0) {
224af57ed9fSAtsushi Murai     (fp->SendConfigReq)(fp);
225af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);	/* Start restart timer */
226af57ed9fSAtsushi Murai     fp->restart--;		/* Decrement restart counter */
227af57ed9fSAtsushi Murai   } else {
228af57ed9fSAtsushi Murai     FsmClose(fp);
229af57ed9fSAtsushi Murai   }
230af57ed9fSAtsushi Murai }
231af57ed9fSAtsushi Murai 
232af57ed9fSAtsushi Murai void
233af57ed9fSAtsushi Murai FsmSendTerminateReq(fp)
234af57ed9fSAtsushi Murai struct fsm *fp;
235af57ed9fSAtsushi Murai {
236cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendTerminateReq.\n");
237af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
238af57ed9fSAtsushi Murai   (fp->SendTerminateReq)(fp);
239af57ed9fSAtsushi Murai   StartTimer(&fp->FsmTimer);	/* Start restart timer */
240af57ed9fSAtsushi Murai   fp->restart--;		/* Decrement restart counter */
241af57ed9fSAtsushi Murai }
242af57ed9fSAtsushi Murai 
243af57ed9fSAtsushi Murai static void
244af57ed9fSAtsushi Murai FsmSendConfigAck(fp, lhp, option, count)
245af57ed9fSAtsushi Murai struct fsm *fp;
246af57ed9fSAtsushi Murai struct fsmheader *lhp;
247af57ed9fSAtsushi Murai u_char *option;
248af57ed9fSAtsushi Murai int count;
249af57ed9fSAtsushi Murai {
250cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]);
25153c9f6c0SAtsushi Murai   (fp->DecodeConfig)(option, count, MODE_NOP);
252af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
253af57ed9fSAtsushi Murai }
254af57ed9fSAtsushi Murai 
255af57ed9fSAtsushi Murai static void
256af57ed9fSAtsushi Murai FsmSendConfigRej(fp, lhp, option, count)
257af57ed9fSAtsushi Murai struct fsm *fp;
258af57ed9fSAtsushi Murai struct fsmheader *lhp;
259af57ed9fSAtsushi Murai u_char *option;
260af57ed9fSAtsushi Murai int count;
261af57ed9fSAtsushi Murai {
262cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]);
26353c9f6c0SAtsushi Murai   (fp->DecodeConfig)(option, count, MODE_NOP);
264af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
265af57ed9fSAtsushi Murai }
266af57ed9fSAtsushi Murai 
267af57ed9fSAtsushi Murai static void
268af57ed9fSAtsushi Murai FsmSendConfigNak(fp, lhp, option, count)
269af57ed9fSAtsushi Murai struct fsm *fp;
270af57ed9fSAtsushi Murai struct fsmheader *lhp;
271af57ed9fSAtsushi Murai u_char *option;
272af57ed9fSAtsushi Murai int count;
273af57ed9fSAtsushi Murai {
274cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]);
27553c9f6c0SAtsushi Murai   (fp->DecodeConfig)(option, count, MODE_NOP);
276af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
277af57ed9fSAtsushi Murai }
278af57ed9fSAtsushi Murai 
279af57ed9fSAtsushi Murai /*
280af57ed9fSAtsushi Murai  *	Timeout actions
281af57ed9fSAtsushi Murai  */
282af57ed9fSAtsushi Murai void
283af57ed9fSAtsushi Murai FsmTimeout(fp)
284af57ed9fSAtsushi Murai struct fsm *fp;
285af57ed9fSAtsushi Murai {
286af57ed9fSAtsushi Murai   if (fp->restart) {
287af57ed9fSAtsushi Murai     switch (fp->state) {
288af57ed9fSAtsushi Murai     case ST_CLOSING:
289af57ed9fSAtsushi Murai     case ST_STOPPING:
290af57ed9fSAtsushi Murai       FsmSendTerminateReq(fp);
291af57ed9fSAtsushi Murai       break;
292af57ed9fSAtsushi Murai     case ST_REQSENT:
293af57ed9fSAtsushi Murai     case ST_ACKSENT:
294af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
295af57ed9fSAtsushi Murai       break;
296af57ed9fSAtsushi Murai     case ST_ACKRCVD:
297af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
298af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
299af57ed9fSAtsushi Murai       break;
300af57ed9fSAtsushi Murai     }
301af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);
302af57ed9fSAtsushi Murai   } else {
303af57ed9fSAtsushi Murai     switch (fp->state) {
304af57ed9fSAtsushi Murai     case ST_CLOSING:
305af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
306af57ed9fSAtsushi Murai       (fp->LayerFinish)(fp);
307af57ed9fSAtsushi Murai       break;
308af57ed9fSAtsushi Murai     case ST_STOPPING:
309af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
310af57ed9fSAtsushi Murai       (fp->LayerFinish)(fp);
311af57ed9fSAtsushi Murai       break;
312af57ed9fSAtsushi Murai     case ST_REQSENT:		/* XXX: 3p */
313af57ed9fSAtsushi Murai     case ST_ACKSENT:
314af57ed9fSAtsushi Murai     case ST_ACKRCVD:
315af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
316af57ed9fSAtsushi Murai       (fp->LayerFinish)(fp);
317af57ed9fSAtsushi Murai       break;
318af57ed9fSAtsushi Murai     }
319af57ed9fSAtsushi Murai   }
320af57ed9fSAtsushi Murai }
321af57ed9fSAtsushi Murai 
322af57ed9fSAtsushi Murai void
323af57ed9fSAtsushi Murai FsmInitRestartCounter(fp)
324af57ed9fSAtsushi Murai struct fsm *fp;
325af57ed9fSAtsushi Murai {
326af57ed9fSAtsushi Murai   StopTimer(&fp->FsmTimer);
327af57ed9fSAtsushi Murai   fp->FsmTimer.state = TIMER_STOPPED;
328af57ed9fSAtsushi Murai   fp->FsmTimer.func = FsmTimeout;
329af57ed9fSAtsushi Murai   fp->FsmTimer.arg = (void *)fp;
330af57ed9fSAtsushi Murai   (fp->InitRestartCounter)(fp);
331af57ed9fSAtsushi Murai }
332af57ed9fSAtsushi Murai 
333af57ed9fSAtsushi Murai /*
334af57ed9fSAtsushi Murai  *   Actions when receive packets
335af57ed9fSAtsushi Murai  */
336af57ed9fSAtsushi Murai void
337af57ed9fSAtsushi Murai FsmRecvConfigReq(fp, lhp, bp)			/* RCR */
338af57ed9fSAtsushi Murai struct fsm *fp;
339af57ed9fSAtsushi Murai struct fsmheader *lhp;
340af57ed9fSAtsushi Murai struct mbuf *bp;
341af57ed9fSAtsushi Murai {
34253c9f6c0SAtsushi Murai   int plen, flen;
343af57ed9fSAtsushi Murai   int ackaction = 0;
344af57ed9fSAtsushi Murai 
345af57ed9fSAtsushi Murai   plen = plength(bp);
34653c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
34753c9f6c0SAtsushi Murai   if (plen < flen) {
348927145beSBrian Somers     LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)", plen, flen);
349af57ed9fSAtsushi Murai     pfree(bp);
350af57ed9fSAtsushi Murai     return;
351af57ed9fSAtsushi Murai   }
352af57ed9fSAtsushi Murai 
35353c9f6c0SAtsushi Murai 
354af57ed9fSAtsushi Murai   /*
355af57ed9fSAtsushi Murai    *  Check and process easy case
356af57ed9fSAtsushi Murai    */
357af57ed9fSAtsushi Murai   switch (fp->state) {
358af57ed9fSAtsushi Murai   case ST_INITIAL:
359af57ed9fSAtsushi Murai   case ST_STARTING:
360cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]);
361af57ed9fSAtsushi Murai     pfree(bp);
362af57ed9fSAtsushi Murai     return;
363af57ed9fSAtsushi Murai   case ST_CLOSED:
364af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
365af57ed9fSAtsushi Murai     pfree(bp);
366af57ed9fSAtsushi Murai     return;
367af57ed9fSAtsushi Murai   case ST_CLOSING:
368af57ed9fSAtsushi Murai   case ST_STOPPING:
369927145beSBrian Somers     LogPrintf(LogERROR, "Got ConfigReq while state = %d\n", fp->state);
370af57ed9fSAtsushi Murai     pfree(bp);
371af57ed9fSAtsushi Murai     return;
372af57ed9fSAtsushi Murai   }
373af57ed9fSAtsushi Murai 
37453c9f6c0SAtsushi Murai   (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_REQ);
375af57ed9fSAtsushi Murai 
376af57ed9fSAtsushi Murai   if (nakp == NakBuff && rejp == RejBuff)
377af57ed9fSAtsushi Murai     ackaction = 1;
378af57ed9fSAtsushi Murai 
379af57ed9fSAtsushi Murai   switch (fp->state) {
380af57ed9fSAtsushi Murai   case ST_OPENED:
381af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
382af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
383af57ed9fSAtsushi Murai     break;
384af57ed9fSAtsushi Murai   case ST_STOPPED:
385af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
386af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
387af57ed9fSAtsushi Murai     break;
388af57ed9fSAtsushi Murai   }
389af57ed9fSAtsushi Murai 
390af57ed9fSAtsushi Murai   if (rejp != RejBuff)
391af57ed9fSAtsushi Murai     FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff);
392af57ed9fSAtsushi Murai   if (nakp != NakBuff)
393af57ed9fSAtsushi Murai     FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff);
394af57ed9fSAtsushi Murai   if (ackaction)
395af57ed9fSAtsushi Murai     FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff);
396af57ed9fSAtsushi Murai 
397af57ed9fSAtsushi Murai   switch (fp->state) {
398af57ed9fSAtsushi Murai   case ST_STOPPED:
399af57ed9fSAtsushi Murai   case ST_OPENED:
400af57ed9fSAtsushi Murai     if (ackaction)
401af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
402af57ed9fSAtsushi Murai     else
403af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
404af57ed9fSAtsushi Murai     break;
405af57ed9fSAtsushi Murai   case ST_REQSENT:
406af57ed9fSAtsushi Murai     if (ackaction)
407af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
408af57ed9fSAtsushi Murai     break;
409af57ed9fSAtsushi Murai   case ST_ACKRCVD:
410af57ed9fSAtsushi Murai     if (ackaction) {
411af57ed9fSAtsushi Murai       NewState(fp, ST_OPENED);
412af57ed9fSAtsushi Murai       (fp->LayerUp)(fp);
413af57ed9fSAtsushi Murai     }
414af57ed9fSAtsushi Murai     break;
415af57ed9fSAtsushi Murai   case ST_ACKSENT:
416af57ed9fSAtsushi Murai     if (!ackaction)
417af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
418af57ed9fSAtsushi Murai     break;
419af57ed9fSAtsushi Murai   }
420af57ed9fSAtsushi Murai   pfree(bp);
421af57ed9fSAtsushi Murai }
422af57ed9fSAtsushi Murai 
423af57ed9fSAtsushi Murai void
424af57ed9fSAtsushi Murai FsmRecvConfigAck(fp, lhp, bp)			/* RCA */
425af57ed9fSAtsushi Murai struct fsm *fp;
426af57ed9fSAtsushi Murai struct fsmheader *lhp;
427af57ed9fSAtsushi Murai struct mbuf *bp;
428af57ed9fSAtsushi Murai {
429af57ed9fSAtsushi Murai   switch (fp->state) {
430af57ed9fSAtsushi Murai   case ST_CLOSED:
431af57ed9fSAtsushi Murai   case ST_STOPPED:
432af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
433af57ed9fSAtsushi Murai     break;
434af57ed9fSAtsushi Murai   case ST_CLOSING:
435af57ed9fSAtsushi Murai   case ST_STOPPING:
436af57ed9fSAtsushi Murai     break;
437af57ed9fSAtsushi Murai   case ST_REQSENT:
438af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
439af57ed9fSAtsushi Murai     NewState(fp, ST_ACKRCVD);
440af57ed9fSAtsushi Murai     break;
441af57ed9fSAtsushi Murai   case ST_ACKRCVD:
442af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
443af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
444af57ed9fSAtsushi Murai     break;
445af57ed9fSAtsushi Murai   case ST_ACKSENT:
446af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
447af57ed9fSAtsushi Murai     NewState(fp, ST_OPENED);
448af57ed9fSAtsushi Murai     (fp->LayerUp)(fp);
449af57ed9fSAtsushi Murai     break;
450af57ed9fSAtsushi Murai   case ST_OPENED:
451af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
452af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
453af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
454af57ed9fSAtsushi Murai     break;
455af57ed9fSAtsushi Murai   }
456af57ed9fSAtsushi Murai   pfree(bp);
457af57ed9fSAtsushi Murai }
458af57ed9fSAtsushi Murai 
459af57ed9fSAtsushi Murai void
460af57ed9fSAtsushi Murai FsmRecvConfigNak(fp, lhp, bp)			/* RCN */
461af57ed9fSAtsushi Murai struct fsm *fp;
462af57ed9fSAtsushi Murai struct fsmheader *lhp;
463af57ed9fSAtsushi Murai struct mbuf *bp;
464af57ed9fSAtsushi Murai {
46553c9f6c0SAtsushi Murai   int plen, flen;
466af57ed9fSAtsushi Murai 
467af57ed9fSAtsushi Murai   plen = plength(bp);
46853c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
46953c9f6c0SAtsushi Murai   if (plen < flen) {
470af57ed9fSAtsushi Murai     pfree(bp);
471af57ed9fSAtsushi Murai     return;
472af57ed9fSAtsushi Murai   }
473af57ed9fSAtsushi Murai 
474af57ed9fSAtsushi Murai   /*
475af57ed9fSAtsushi Murai    *  Check and process easy case
476af57ed9fSAtsushi Murai    */
477af57ed9fSAtsushi Murai   switch (fp->state) {
478af57ed9fSAtsushi Murai   case ST_INITIAL:
479af57ed9fSAtsushi Murai   case ST_STARTING:
480cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", StateNames[fp->state]);
481af57ed9fSAtsushi Murai     pfree(bp);
482af57ed9fSAtsushi Murai     return;
483af57ed9fSAtsushi Murai   case ST_CLOSED:
484af57ed9fSAtsushi Murai   case ST_STOPPED:
485af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
486af57ed9fSAtsushi Murai     pfree(bp);
487af57ed9fSAtsushi Murai     return;
488af57ed9fSAtsushi Murai   case ST_CLOSING:
489af57ed9fSAtsushi Murai   case ST_STOPPING:
490af57ed9fSAtsushi Murai     pfree(bp);
491af57ed9fSAtsushi Murai     return;
492af57ed9fSAtsushi Murai   }
493af57ed9fSAtsushi Murai 
49453c9f6c0SAtsushi Murai   (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_NAK);
495af57ed9fSAtsushi Murai 
496af57ed9fSAtsushi Murai   switch (fp->state) {
497af57ed9fSAtsushi Murai   case ST_REQSENT:
498af57ed9fSAtsushi Murai   case ST_ACKSENT:
499af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
500af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
501af57ed9fSAtsushi Murai     break;
502af57ed9fSAtsushi Murai   case ST_OPENED:
503af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
504af57ed9fSAtsushi Murai     /* Fall down */
505af57ed9fSAtsushi Murai   case ST_ACKRCVD:
506af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
507af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
508af57ed9fSAtsushi Murai     break;
509af57ed9fSAtsushi Murai   }
510af57ed9fSAtsushi Murai 
511af57ed9fSAtsushi Murai   pfree(bp);
512af57ed9fSAtsushi Murai }
513af57ed9fSAtsushi Murai 
514af57ed9fSAtsushi Murai void
515af57ed9fSAtsushi Murai FsmRecvTermReq(fp, lhp, bp)				/* RTR */
516af57ed9fSAtsushi Murai struct fsm *fp;
517af57ed9fSAtsushi Murai struct fsmheader *lhp;
518af57ed9fSAtsushi Murai struct mbuf *bp;
519af57ed9fSAtsushi Murai {
520af57ed9fSAtsushi Murai   switch (fp->state) {
521af57ed9fSAtsushi Murai   case ST_INITIAL:
522af57ed9fSAtsushi Murai   case ST_STARTING:
523cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", StateNames[fp->state]);
524af57ed9fSAtsushi Murai     break;
525af57ed9fSAtsushi Murai   case ST_CLOSED:
526af57ed9fSAtsushi Murai   case ST_STOPPED:
527af57ed9fSAtsushi Murai   case ST_CLOSING:
528af57ed9fSAtsushi Murai   case ST_STOPPING:
529af57ed9fSAtsushi Murai   case ST_REQSENT:
530af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
531af57ed9fSAtsushi Murai     break;
532af57ed9fSAtsushi Murai   case ST_ACKRCVD:
533af57ed9fSAtsushi Murai   case ST_ACKSENT:
534af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
535af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
536af57ed9fSAtsushi Murai     break;
537af57ed9fSAtsushi Murai   case ST_OPENED:
5388f2fa0eeSBrian Somers     (fp->LayerDown)(fp);
539af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
5408f2fa0eeSBrian Somers     StartTimer(&fp->FsmTimer);	/* Start restart timer */
5418f2fa0eeSBrian Somers     fp->restart = 0;
5428f2fa0eeSBrian Somers     NewState(fp, ST_STOPPING);
543af57ed9fSAtsushi Murai     break;
544af57ed9fSAtsushi Murai   }
545af57ed9fSAtsushi Murai   pfree(bp);
546af57ed9fSAtsushi Murai }
547af57ed9fSAtsushi Murai 
548af57ed9fSAtsushi Murai void
549af57ed9fSAtsushi Murai FsmRecvTermAck(fp, lhp, bp)			/* RTA */
550af57ed9fSAtsushi Murai struct fsm *fp;
551af57ed9fSAtsushi Murai struct fsmheader *lhp;
552af57ed9fSAtsushi Murai struct mbuf *bp;
553af57ed9fSAtsushi Murai {
554af57ed9fSAtsushi Murai   switch (fp->state) {
555af57ed9fSAtsushi Murai   case ST_CLOSING:
556af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
557af57ed9fSAtsushi Murai     (fp->LayerFinish)(fp);
558af57ed9fSAtsushi Murai     break;
559af57ed9fSAtsushi Murai   case ST_STOPPING:
560af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPED);
561af57ed9fSAtsushi Murai     (fp->LayerFinish)(fp);
562af57ed9fSAtsushi Murai     break;
563af57ed9fSAtsushi Murai   case ST_ACKRCVD:
564af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
565af57ed9fSAtsushi Murai     break;
566af57ed9fSAtsushi Murai   case ST_OPENED:
567af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
568af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
569af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
570af57ed9fSAtsushi Murai     break;
571af57ed9fSAtsushi Murai   }
572af57ed9fSAtsushi Murai   pfree(bp);
573af57ed9fSAtsushi Murai }
574af57ed9fSAtsushi Murai 
575af57ed9fSAtsushi Murai void
576af57ed9fSAtsushi Murai FsmRecvConfigRej(fp, lhp, bp)			/* RCJ */
577af57ed9fSAtsushi Murai struct fsm *fp;
578af57ed9fSAtsushi Murai struct fsmheader *lhp;
579af57ed9fSAtsushi Murai struct mbuf *bp;
580af57ed9fSAtsushi Murai {
58153c9f6c0SAtsushi Murai   int plen, flen;
582af57ed9fSAtsushi Murai 
583af57ed9fSAtsushi Murai   plen = plength(bp);
58453c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
58553c9f6c0SAtsushi Murai   if (plen < flen) {
586af57ed9fSAtsushi Murai     pfree(bp);
587af57ed9fSAtsushi Murai     return;
588af57ed9fSAtsushi Murai   }
589cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvConfigRej.\n");
590af57ed9fSAtsushi Murai 
591af57ed9fSAtsushi Murai   /*
592af57ed9fSAtsushi Murai    *  Check and process easy case
593af57ed9fSAtsushi Murai    */
594af57ed9fSAtsushi Murai   switch (fp->state) {
595af57ed9fSAtsushi Murai   case ST_INITIAL:
596af57ed9fSAtsushi Murai   case ST_STARTING:
597cb611434SBrian Somers     LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", StateNames[fp->state]);
598af57ed9fSAtsushi Murai     pfree(bp);
599af57ed9fSAtsushi Murai     return;
600af57ed9fSAtsushi Murai   case ST_CLOSED:
601af57ed9fSAtsushi Murai   case ST_STOPPED:
602af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
603af57ed9fSAtsushi Murai     pfree(bp);
604af57ed9fSAtsushi Murai     return;
605af57ed9fSAtsushi Murai   case ST_CLOSING:
606af57ed9fSAtsushi Murai   case ST_STOPPING:
607af57ed9fSAtsushi Murai     pfree(bp);
608af57ed9fSAtsushi Murai     return;
609af57ed9fSAtsushi Murai   }
610af57ed9fSAtsushi Murai 
61153c9f6c0SAtsushi Murai   (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_REJ);
612af57ed9fSAtsushi Murai 
613af57ed9fSAtsushi Murai   switch (fp->state) {
614af57ed9fSAtsushi Murai   case ST_REQSENT:
615af57ed9fSAtsushi Murai   case ST_ACKSENT:
616af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
617af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
618af57ed9fSAtsushi Murai     break;
619af57ed9fSAtsushi Murai   case ST_OPENED:
620af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
621af57ed9fSAtsushi Murai     /* Fall down */
622af57ed9fSAtsushi Murai   case ST_ACKRCVD:
623af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
624af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
625af57ed9fSAtsushi Murai     break;
626af57ed9fSAtsushi Murai   }
627af57ed9fSAtsushi Murai   pfree(bp);
628af57ed9fSAtsushi Murai }
629af57ed9fSAtsushi Murai 
630af57ed9fSAtsushi Murai void
631af57ed9fSAtsushi Murai FsmRecvCodeRej(fp, lhp, bp)
632af57ed9fSAtsushi Murai struct fsm *fp;
633af57ed9fSAtsushi Murai struct fsmheader *lhp;
634af57ed9fSAtsushi Murai struct mbuf *bp;
635af57ed9fSAtsushi Murai {
636cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvCodeRej\n");
637af57ed9fSAtsushi Murai   pfree(bp);
638af57ed9fSAtsushi Murai }
639af57ed9fSAtsushi Murai 
640af57ed9fSAtsushi Murai void
641af57ed9fSAtsushi Murai FsmRecvProtoRej(fp, lhp, bp)
642af57ed9fSAtsushi Murai struct fsm *fp;
643af57ed9fSAtsushi Murai struct fsmheader *lhp;
644af57ed9fSAtsushi Murai struct mbuf *bp;
645af57ed9fSAtsushi Murai {
646af57ed9fSAtsushi Murai   u_short *sp, proto;
647af57ed9fSAtsushi Murai 
648af57ed9fSAtsushi Murai   sp = (u_short *)MBUF_CTOP(bp);
649af57ed9fSAtsushi Murai   proto = ntohs(*sp);
650cb611434SBrian Somers   LogPrintf(fp->LogLevel, "-- Protocol (%04x) was rejected.\n", proto);
651af57ed9fSAtsushi Murai 
652af57ed9fSAtsushi Murai   switch (proto) {
653af57ed9fSAtsushi Murai   case PROTO_LQR:
654af57ed9fSAtsushi Murai     StopLqr(LQM_LQR);
655af57ed9fSAtsushi Murai     break;
656af57ed9fSAtsushi Murai   case PROTO_CCP:
657af57ed9fSAtsushi Murai     fp = &CcpFsm;
658af57ed9fSAtsushi Murai     (fp->LayerFinish)(fp);
659af57ed9fSAtsushi Murai     switch (fp->state) {
660af57ed9fSAtsushi Murai     case ST_CLOSED:
661af57ed9fSAtsushi Murai     case ST_CLOSING:
662af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
663af57ed9fSAtsushi Murai     default:
664af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
665af57ed9fSAtsushi Murai       break;
666af57ed9fSAtsushi Murai     }
667af57ed9fSAtsushi Murai     break;
668af57ed9fSAtsushi Murai   }
669af57ed9fSAtsushi Murai   pfree(bp);
670af57ed9fSAtsushi Murai }
671af57ed9fSAtsushi Murai 
672af57ed9fSAtsushi Murai void
673af57ed9fSAtsushi Murai FsmRecvEchoReq(fp, lhp, bp)
674af57ed9fSAtsushi Murai struct fsm *fp;
675af57ed9fSAtsushi Murai struct fsmheader *lhp;
676af57ed9fSAtsushi Murai struct mbuf *bp;
677af57ed9fSAtsushi Murai {
678af57ed9fSAtsushi Murai   u_char *cp;
679af57ed9fSAtsushi Murai   u_long *lp, magic;
680af57ed9fSAtsushi Murai 
681af57ed9fSAtsushi Murai   cp = MBUF_CTOP(bp);
682af57ed9fSAtsushi Murai   lp = (u_long *)cp;
683af57ed9fSAtsushi Murai   magic = ntohl(*lp);
684af57ed9fSAtsushi Murai   if (magic != LcpInfo.his_magic) {
685927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n");
686af57ed9fSAtsushi Murai     /* XXX: We should send terminate request */
687af57ed9fSAtsushi Murai   }
688af57ed9fSAtsushi Murai 
689af57ed9fSAtsushi Murai   if (fp->state == ST_OPENED) {
690af57ed9fSAtsushi Murai     *lp = htonl(LcpInfo.want_magic);	/* Insert local magic number */
691cb611434SBrian Somers     LogPrintf(fp->LogLevel, "SendEchoRep(%s)\n", StateNames[fp->state]);
692af57ed9fSAtsushi Murai     FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp));
693af57ed9fSAtsushi Murai   }
694af57ed9fSAtsushi Murai   pfree(bp);
695af57ed9fSAtsushi Murai }
696af57ed9fSAtsushi Murai 
697af57ed9fSAtsushi Murai void
698af57ed9fSAtsushi Murai FsmRecvEchoRep(fp, lhp, bp)
699af57ed9fSAtsushi Murai struct fsm *fp;
700af57ed9fSAtsushi Murai struct fsmheader *lhp;
701af57ed9fSAtsushi Murai struct mbuf *bp;
702af57ed9fSAtsushi Murai {
703af57ed9fSAtsushi Murai   u_long *lp, magic;
704af57ed9fSAtsushi Murai 
705af57ed9fSAtsushi Murai   lp = (u_long *)MBUF_CTOP(bp);
706af57ed9fSAtsushi Murai   magic = ntohl(*lp);
70785c59f05SJoerg Wunsch /*
70885c59f05SJoerg Wunsch  * Tolerate echo replies with either magic number
70985c59f05SJoerg Wunsch  */
71085c59f05SJoerg Wunsch   if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) {
711927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n",
712af57ed9fSAtsushi Murai 	LcpInfo.his_magic, magic);
713af57ed9fSAtsushi Murai     /*
714af57ed9fSAtsushi Murai      *  XXX: We should send terminate request. But poor implementation
715af57ed9fSAtsushi Murai      *       may die as a result.
716af57ed9fSAtsushi Murai      */
717af57ed9fSAtsushi Murai   }
718af57ed9fSAtsushi Murai   RecvEchoLqr(bp);
719af57ed9fSAtsushi Murai   pfree(bp);
720af57ed9fSAtsushi Murai }
721af57ed9fSAtsushi Murai 
722af57ed9fSAtsushi Murai void
723af57ed9fSAtsushi Murai FsmRecvDiscReq(fp, lhp, bp)
724af57ed9fSAtsushi Murai struct fsm *fp;
725af57ed9fSAtsushi Murai struct fsmheader *lhp;
726af57ed9fSAtsushi Murai struct mbuf *bp;
727af57ed9fSAtsushi Murai {
728cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvDiscReq\n");
729af57ed9fSAtsushi Murai   pfree(bp);
730af57ed9fSAtsushi Murai }
731af57ed9fSAtsushi Murai 
732af57ed9fSAtsushi Murai void
733af57ed9fSAtsushi Murai FsmRecvIdent(fp, lhp, bp)
734af57ed9fSAtsushi Murai struct fsm *fp;
735af57ed9fSAtsushi Murai struct fsmheader *lhp;
736af57ed9fSAtsushi Murai struct mbuf *bp;
737af57ed9fSAtsushi Murai {
738cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvIdent\n");
739af57ed9fSAtsushi Murai   pfree(bp);
740af57ed9fSAtsushi Murai }
741af57ed9fSAtsushi Murai 
742af57ed9fSAtsushi Murai void
743af57ed9fSAtsushi Murai FsmRecvTimeRemain(fp, lhp, bp)
744af57ed9fSAtsushi Murai struct fsm *fp;
745af57ed9fSAtsushi Murai struct fsmheader *lhp;
746af57ed9fSAtsushi Murai struct mbuf *bp;
747af57ed9fSAtsushi Murai {
748cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvTimeRemain\n");
749af57ed9fSAtsushi Murai   pfree(bp);
750af57ed9fSAtsushi Murai }
751af57ed9fSAtsushi Murai 
752af57ed9fSAtsushi Murai void
753af57ed9fSAtsushi Murai FsmRecvResetReq(fp, lhp, bp)
754af57ed9fSAtsushi Murai struct fsm *fp;
755af57ed9fSAtsushi Murai struct fsmheader *lhp;
756af57ed9fSAtsushi Murai struct mbuf *bp;
757af57ed9fSAtsushi Murai {
758cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetReq\n");
759af57ed9fSAtsushi Murai   CcpRecvResetReq(fp);
760cb611434SBrian Somers   LogPrintf(fp->LogLevel, "SendResetAck\n");
761af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0);
762af57ed9fSAtsushi Murai   pfree(bp);
763af57ed9fSAtsushi Murai }
764af57ed9fSAtsushi Murai 
765af57ed9fSAtsushi Murai void
766af57ed9fSAtsushi Murai FsmRecvResetAck(fp, lhp, bp)
767af57ed9fSAtsushi Murai struct fsm *fp;
768af57ed9fSAtsushi Murai struct fsmheader *lhp;
769af57ed9fSAtsushi Murai struct mbuf *bp;
770af57ed9fSAtsushi Murai {
771cb611434SBrian Somers   LogPrintf(fp->LogLevel, "RecvResetAck\n");
772af57ed9fSAtsushi Murai   fp->reqid++;
773af57ed9fSAtsushi Murai   pfree(bp);
774af57ed9fSAtsushi Murai }
775af57ed9fSAtsushi Murai 
776af57ed9fSAtsushi Murai struct fsmcodedesc FsmCodes[] = {
777af57ed9fSAtsushi Murai  { FsmRecvConfigReq,  "Configure Request", },
778af57ed9fSAtsushi Murai  { FsmRecvConfigAck,  "Configure Ack", },
779af57ed9fSAtsushi Murai  { FsmRecvConfigNak,  "Configure Nak", },
780af57ed9fSAtsushi Murai  { FsmRecvConfigRej,  "Configure Reject", },
781af57ed9fSAtsushi Murai  { FsmRecvTermReq,    "Terminate Request", },
782af57ed9fSAtsushi Murai  { FsmRecvTermAck,    "Terminate Ack", },
783af57ed9fSAtsushi Murai  { FsmRecvCodeRej,    "Code Reject", },
784af57ed9fSAtsushi Murai  { FsmRecvProtoRej,   "Protocol Reject", },
785af57ed9fSAtsushi Murai  { FsmRecvEchoReq,    "Echo Request", },
786af57ed9fSAtsushi Murai  { FsmRecvEchoRep,    "Echo Reply", },
787af57ed9fSAtsushi Murai  { FsmRecvDiscReq,    "Discard Request", },
788af57ed9fSAtsushi Murai  { FsmRecvIdent,      "Ident", },
789af57ed9fSAtsushi Murai  { FsmRecvTimeRemain, "Time Remain", },
790af57ed9fSAtsushi Murai  { FsmRecvResetReq,   "Reset Request", },
791af57ed9fSAtsushi Murai  { FsmRecvResetAck,   "Reset Ack", },
792af57ed9fSAtsushi Murai };
793af57ed9fSAtsushi Murai 
794af57ed9fSAtsushi Murai void
795af57ed9fSAtsushi Murai FsmInput(fp, bp)
796af57ed9fSAtsushi Murai struct fsm *fp;
797af57ed9fSAtsushi Murai struct mbuf *bp;
798af57ed9fSAtsushi Murai {
799af57ed9fSAtsushi Murai   int len;
800af57ed9fSAtsushi Murai   struct fsmheader *lhp;
801af57ed9fSAtsushi Murai   struct fsmcodedesc *codep;
802af57ed9fSAtsushi Murai 
803af57ed9fSAtsushi Murai   len = plength(bp);
804af57ed9fSAtsushi Murai   if (len < sizeof(struct fsmheader)) {
805af57ed9fSAtsushi Murai     pfree(bp);
806af57ed9fSAtsushi Murai     return;
807af57ed9fSAtsushi Murai   }
808af57ed9fSAtsushi Murai   lhp = (struct fsmheader *)MBUF_CTOP(bp);
809af57ed9fSAtsushi Murai   if (lhp->code == 0 || lhp->code > fp->max_code) {
810af57ed9fSAtsushi Murai     pfree(bp);		/* XXX: Should send code reject */
811af57ed9fSAtsushi Murai     return;
812af57ed9fSAtsushi Murai   }
813af57ed9fSAtsushi Murai 
814af57ed9fSAtsushi Murai   bp->offset += sizeof(struct fsmheader);
815af57ed9fSAtsushi Murai   bp->cnt -= sizeof(struct fsmheader);
816af57ed9fSAtsushi Murai 
817af57ed9fSAtsushi Murai   codep = FsmCodes + lhp->code - 1;
818cb611434SBrian Somers   LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n",
819927145beSBrian Somers     codep->name, lhp->id, StateNames[fp->state], fp->state);
820927145beSBrian Somers   if (LogIsKept(LogDEBUG))
821af57ed9fSAtsushi Murai     LogMemory();
822af57ed9fSAtsushi Murai   (codep->action)(fp, lhp, bp);
823927145beSBrian Somers   if (LogIsKept(LogDEBUG))
824af57ed9fSAtsushi Murai     LogMemory();
825af57ed9fSAtsushi Murai }
826