xref: /freebsd/usr.sbin/ppp/fsm.c (revision 71144dc552f9a442d3fd2cc0d2f664cd8b5b7c00)
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  *
2071144dc5SBrian Somers  * $Id: fsm.c,v 1.13 1997/06/09 03:27:21 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 /*
4771144dc5SBrian Somers  * This timer times the ST_STOPPED state out after the given value
4871144dc5SBrian Somers  * (specified via "set stopped ...").  Although this isn't
4971144dc5SBrian Somers  * specified in the rfc, the rfc *does* say that "the application
5071144dc5SBrian Somers  * may use higher level timers to avoid deadlock".
5171144dc5SBrian Somers  * The StoppedTimer takes effect when the other side ABENDs rather
5271144dc5SBrian Somers  * than going into ST_ACKSENT (and sending the ACK), causing ppp to
5371144dc5SBrian Somers  * time out and drop into ST_STOPPED.  At this point, nothing will
5471144dc5SBrian Somers  * change this state :-(
5571144dc5SBrian Somers  */
5671144dc5SBrian Somers struct pppTimer StoppedTimer;
5771144dc5SBrian Somers 
5871144dc5SBrian Somers static void
5971144dc5SBrian Somers StoppedTimeout(fp)
6071144dc5SBrian Somers struct fsm *fp;
6171144dc5SBrian Somers {
6271144dc5SBrian Somers   LogPrintf(LogLCP, "Stopped timer expired\n");
6371144dc5SBrian Somers   if (modem != -1)
6471144dc5SBrian Somers     DownConnection();
6571144dc5SBrian Somers   else
6671144dc5SBrian Somers     FsmDown(fp);
6771144dc5SBrian Somers }
6871144dc5SBrian Somers 
69af57ed9fSAtsushi Murai void
70af57ed9fSAtsushi Murai FsmInit(fp)
71af57ed9fSAtsushi Murai struct fsm *fp;
72af57ed9fSAtsushi Murai {
73927145beSBrian Somers   LogPrintf(LogDEBUG, "FsmInit\n");
74af57ed9fSAtsushi Murai   fp->state = ST_INITIAL;
75af57ed9fSAtsushi Murai   fp->reqid = 1;
76af57ed9fSAtsushi Murai   fp->restart = 1;
77af57ed9fSAtsushi Murai   fp->maxconfig = 3;
78af57ed9fSAtsushi Murai }
79af57ed9fSAtsushi Murai 
80af57ed9fSAtsushi Murai void
81af57ed9fSAtsushi Murai NewState(fp, new)
82af57ed9fSAtsushi Murai struct fsm *fp;
83af57ed9fSAtsushi Murai int new;
84af57ed9fSAtsushi Murai {
85927145beSBrian Somers   LogPrintf(LogLCP, "State change %s --> %s\n",
86927145beSBrian Somers 	  StateNames[fp->state], StateNames[new]);
8771144dc5SBrian Somers   if (fp->state == ST_STOPPED && StoppedTimer.state == TIMER_RUNNING)
8871144dc5SBrian Somers       StopTimer(&StoppedTimer);
89af57ed9fSAtsushi Murai   fp->state = new;
9071144dc5SBrian Somers   if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
91af57ed9fSAtsushi Murai     StopTimer(&fp->FsmTimer);
9271144dc5SBrian Somers     if (new == ST_STOPPED && VarStoppedTimeout) {
9371144dc5SBrian Somers       StoppedTimer.state = TIMER_STOPPED;
9471144dc5SBrian Somers       StoppedTimer.func = StoppedTimeout;
9571144dc5SBrian Somers       StoppedTimer.arg = (void *)fp;
9671144dc5SBrian Somers       StoppedTimer.load = VarStoppedTimeout * SECTICKS;
9771144dc5SBrian Somers       StartTimer(&StoppedTimer);
9871144dc5SBrian Somers     }
9971144dc5SBrian Somers   }
100af57ed9fSAtsushi Murai }
101af57ed9fSAtsushi Murai 
102af57ed9fSAtsushi Murai void
103af57ed9fSAtsushi Murai FsmOutput(fp, code, id, ptr, count)
104af57ed9fSAtsushi Murai struct fsm *fp;
105af57ed9fSAtsushi Murai u_int code, id;
106af57ed9fSAtsushi Murai u_char *ptr;
107af57ed9fSAtsushi Murai 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);
118af57ed9fSAtsushi Murai   bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader));
119af57ed9fSAtsushi Murai   if (count)
120af57ed9fSAtsushi Murai     bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count);
121927145beSBrian Somers   LogDumpBp(LogDEBUG, "FsmOutput", bp);
12276bd0c0aSDoug Rabson   HdlcOutput(PRI_LINK, fp->proto, bp);
123af57ed9fSAtsushi Murai }
124af57ed9fSAtsushi Murai 
125af57ed9fSAtsushi Murai void
126af57ed9fSAtsushi Murai FsmOpen(fp)
127af57ed9fSAtsushi Murai 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
159af57ed9fSAtsushi Murai FsmUp(fp)
160af57ed9fSAtsushi Murai struct fsm *fp;
161af57ed9fSAtsushi Murai {
162af57ed9fSAtsushi Murai   switch (fp->state) {
163af57ed9fSAtsushi Murai   case ST_INITIAL:
164af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
165af57ed9fSAtsushi Murai     break;
166af57ed9fSAtsushi Murai   case ST_STARTING:
167af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
168af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
169af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
170af57ed9fSAtsushi Murai     break;
171af57ed9fSAtsushi Murai   default:
172927145beSBrian Somers     LogPrintf(LogLCP, "Oops, Up at %s\n", StateNames[fp->state]);
173af57ed9fSAtsushi Murai     break;
174af57ed9fSAtsushi Murai   }
175af57ed9fSAtsushi Murai }
176af57ed9fSAtsushi Murai 
177af57ed9fSAtsushi Murai void
178af57ed9fSAtsushi Murai FsmDown(fp)
179af57ed9fSAtsushi Murai struct fsm *fp;
180af57ed9fSAtsushi Murai {
181af57ed9fSAtsushi Murai   switch (fp->state) {
182af57ed9fSAtsushi Murai   case ST_CLOSED:
183af57ed9fSAtsushi Murai   case ST_CLOSING:
184af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
185af57ed9fSAtsushi Murai     break;
186af57ed9fSAtsushi Murai   case ST_STOPPED:
187af57ed9fSAtsushi Murai     (fp->LayerStart)(fp);
188af57ed9fSAtsushi Murai     /* Fall into.. */
189af57ed9fSAtsushi Murai   case ST_STOPPING:
190af57ed9fSAtsushi Murai   case ST_REQSENT:
191af57ed9fSAtsushi Murai   case ST_ACKRCVD:
192af57ed9fSAtsushi Murai   case ST_ACKSENT:
193af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
194af57ed9fSAtsushi Murai     break;
195af57ed9fSAtsushi Murai   case ST_OPENED:
196af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
197af57ed9fSAtsushi Murai     NewState(fp, ST_STARTING);
198af57ed9fSAtsushi Murai     break;
199af57ed9fSAtsushi Murai   }
200af57ed9fSAtsushi Murai }
201af57ed9fSAtsushi Murai 
202af57ed9fSAtsushi Murai void
203af57ed9fSAtsushi Murai FsmClose(fp)
204af57ed9fSAtsushi Murai struct fsm *fp;
205af57ed9fSAtsushi Murai {
206af57ed9fSAtsushi Murai   switch (fp->state) {
207af57ed9fSAtsushi Murai   case ST_STARTING:
208af57ed9fSAtsushi Murai     NewState(fp, ST_INITIAL);
209af57ed9fSAtsushi Murai     break;
210af57ed9fSAtsushi Murai   case ST_STOPPED:
211af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
212af57ed9fSAtsushi Murai     break;
213af57ed9fSAtsushi Murai   case ST_STOPPING:
214af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
215af57ed9fSAtsushi Murai     break;
216af57ed9fSAtsushi Murai   case ST_OPENED:
217af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
218af57ed9fSAtsushi Murai     /* Fall down */
219af57ed9fSAtsushi Murai   case ST_REQSENT:
220af57ed9fSAtsushi Murai   case ST_ACKRCVD:
221af57ed9fSAtsushi Murai   case ST_ACKSENT:
222af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
223af57ed9fSAtsushi Murai     FsmSendTerminateReq(fp);
224af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSING);
225af57ed9fSAtsushi Murai     break;
226af57ed9fSAtsushi Murai   }
227af57ed9fSAtsushi Murai }
228af57ed9fSAtsushi Murai 
229af57ed9fSAtsushi Murai /*
230af57ed9fSAtsushi Murai  *	Send functions
231af57ed9fSAtsushi Murai  */
232af57ed9fSAtsushi Murai void
233af57ed9fSAtsushi Murai FsmSendConfigReq(fp)
234af57ed9fSAtsushi Murai struct fsm *fp;
235af57ed9fSAtsushi Murai {
236af57ed9fSAtsushi Murai   if (--fp->maxconfig > 0) {
237af57ed9fSAtsushi Murai     (fp->SendConfigReq)(fp);
238af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);	/* Start restart timer */
239af57ed9fSAtsushi Murai     fp->restart--;		/* Decrement restart counter */
240af57ed9fSAtsushi Murai   } else {
241af57ed9fSAtsushi Murai     FsmClose(fp);
242af57ed9fSAtsushi Murai   }
243af57ed9fSAtsushi Murai }
244af57ed9fSAtsushi Murai 
245af57ed9fSAtsushi Murai void
246af57ed9fSAtsushi Murai FsmSendTerminateReq(fp)
247af57ed9fSAtsushi Murai struct fsm *fp;
248af57ed9fSAtsushi Murai {
249927145beSBrian Somers   LogPrintf(LogLCP, "SendTerminateReq.\n");
250af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
251af57ed9fSAtsushi Murai   (fp->SendTerminateReq)(fp);
252af57ed9fSAtsushi Murai   StartTimer(&fp->FsmTimer);	/* Start restart timer */
253af57ed9fSAtsushi Murai   fp->restart--;		/* Decrement restart counter */
254af57ed9fSAtsushi Murai }
255af57ed9fSAtsushi Murai 
256af57ed9fSAtsushi Murai static void
257af57ed9fSAtsushi Murai FsmSendConfigAck(fp, lhp, option, count)
258af57ed9fSAtsushi Murai struct fsm *fp;
259af57ed9fSAtsushi Murai struct fsmheader *lhp;
260af57ed9fSAtsushi Murai u_char *option;
261af57ed9fSAtsushi Murai int count;
262af57ed9fSAtsushi Murai {
263927145beSBrian Somers   LogPrintf(LogLCP, "SendConfigAck(%s)\n", StateNames[fp->state]);
26453c9f6c0SAtsushi Murai   (fp->DecodeConfig)(option, count, MODE_NOP);
265af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
266af57ed9fSAtsushi Murai }
267af57ed9fSAtsushi Murai 
268af57ed9fSAtsushi Murai static void
269af57ed9fSAtsushi Murai FsmSendConfigRej(fp, lhp, option, count)
270af57ed9fSAtsushi Murai struct fsm *fp;
271af57ed9fSAtsushi Murai struct fsmheader *lhp;
272af57ed9fSAtsushi Murai u_char *option;
273af57ed9fSAtsushi Murai int count;
274af57ed9fSAtsushi Murai {
275927145beSBrian Somers   LogPrintf(LogLCP, "SendConfigRej(%s)\n", StateNames[fp->state]);
27653c9f6c0SAtsushi Murai   (fp->DecodeConfig)(option, count, MODE_NOP);
277af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
278af57ed9fSAtsushi Murai }
279af57ed9fSAtsushi Murai 
280af57ed9fSAtsushi Murai static void
281af57ed9fSAtsushi Murai FsmSendConfigNak(fp, lhp, option, count)
282af57ed9fSAtsushi Murai struct fsm *fp;
283af57ed9fSAtsushi Murai struct fsmheader *lhp;
284af57ed9fSAtsushi Murai u_char *option;
285af57ed9fSAtsushi Murai int count;
286af57ed9fSAtsushi Murai {
287927145beSBrian Somers   LogPrintf(LogLCP, "SendConfigNak(%s)\n", StateNames[fp->state]);
28853c9f6c0SAtsushi Murai   (fp->DecodeConfig)(option, count, MODE_NOP);
289af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
290af57ed9fSAtsushi Murai }
291af57ed9fSAtsushi Murai 
292af57ed9fSAtsushi Murai /*
293af57ed9fSAtsushi Murai  *	Timeout actions
294af57ed9fSAtsushi Murai  */
295af57ed9fSAtsushi Murai void
296af57ed9fSAtsushi Murai FsmTimeout(fp)
297af57ed9fSAtsushi Murai struct fsm *fp;
298af57ed9fSAtsushi Murai {
299af57ed9fSAtsushi Murai   if (fp->restart) {
300af57ed9fSAtsushi Murai     switch (fp->state) {
301af57ed9fSAtsushi Murai     case ST_CLOSING:
302af57ed9fSAtsushi Murai     case ST_STOPPING:
303af57ed9fSAtsushi Murai       FsmSendTerminateReq(fp);
304af57ed9fSAtsushi Murai       break;
305af57ed9fSAtsushi Murai     case ST_REQSENT:
306af57ed9fSAtsushi Murai     case ST_ACKSENT:
307af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
308af57ed9fSAtsushi Murai       break;
309af57ed9fSAtsushi Murai     case ST_ACKRCVD:
310af57ed9fSAtsushi Murai       FsmSendConfigReq(fp);
311af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
312af57ed9fSAtsushi Murai       break;
313af57ed9fSAtsushi Murai     }
314af57ed9fSAtsushi Murai     StartTimer(&fp->FsmTimer);
315af57ed9fSAtsushi Murai   } else {
316af57ed9fSAtsushi Murai     switch (fp->state) {
317af57ed9fSAtsushi Murai     case ST_CLOSING:
318af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
319af57ed9fSAtsushi Murai       (fp->LayerFinish)(fp);
320af57ed9fSAtsushi Murai       break;
321af57ed9fSAtsushi Murai     case ST_STOPPING:
322af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
323af57ed9fSAtsushi Murai       (fp->LayerFinish)(fp);
324af57ed9fSAtsushi Murai       break;
325af57ed9fSAtsushi Murai     case ST_REQSENT:		/* XXX: 3p */
326af57ed9fSAtsushi Murai     case ST_ACKSENT:
327af57ed9fSAtsushi Murai     case ST_ACKRCVD:
328af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
329af57ed9fSAtsushi Murai       (fp->LayerFinish)(fp);
330af57ed9fSAtsushi Murai       break;
331af57ed9fSAtsushi Murai     }
332af57ed9fSAtsushi Murai   }
333af57ed9fSAtsushi Murai }
334af57ed9fSAtsushi Murai 
335af57ed9fSAtsushi Murai void
336af57ed9fSAtsushi Murai FsmInitRestartCounter(fp)
337af57ed9fSAtsushi Murai struct fsm *fp;
338af57ed9fSAtsushi Murai {
339af57ed9fSAtsushi Murai   StopTimer(&fp->FsmTimer);
340af57ed9fSAtsushi Murai   fp->FsmTimer.state = TIMER_STOPPED;
341af57ed9fSAtsushi Murai   fp->FsmTimer.func = FsmTimeout;
342af57ed9fSAtsushi Murai   fp->FsmTimer.arg = (void *)fp;
343af57ed9fSAtsushi Murai   (fp->InitRestartCounter)(fp);
344af57ed9fSAtsushi Murai }
345af57ed9fSAtsushi Murai 
346af57ed9fSAtsushi Murai /*
347af57ed9fSAtsushi Murai  *   Actions when receive packets
348af57ed9fSAtsushi Murai  */
349af57ed9fSAtsushi Murai void
350af57ed9fSAtsushi Murai FsmRecvConfigReq(fp, lhp, bp)			/* RCR */
351af57ed9fSAtsushi Murai struct fsm *fp;
352af57ed9fSAtsushi Murai struct fsmheader *lhp;
353af57ed9fSAtsushi Murai struct mbuf *bp;
354af57ed9fSAtsushi Murai {
35553c9f6c0SAtsushi Murai   int plen, flen;
356af57ed9fSAtsushi Murai   int ackaction = 0;
357af57ed9fSAtsushi Murai 
358af57ed9fSAtsushi Murai   plen = plength(bp);
35953c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
36053c9f6c0SAtsushi Murai   if (plen < flen) {
361927145beSBrian Somers     LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)", plen, flen);
362af57ed9fSAtsushi Murai     pfree(bp);
363af57ed9fSAtsushi Murai     return;
364af57ed9fSAtsushi Murai   }
365af57ed9fSAtsushi Murai 
36653c9f6c0SAtsushi Murai 
367af57ed9fSAtsushi Murai   /*
368af57ed9fSAtsushi Murai    *  Check and process easy case
369af57ed9fSAtsushi Murai    */
370af57ed9fSAtsushi Murai   switch (fp->state) {
371af57ed9fSAtsushi Murai   case ST_INITIAL:
372af57ed9fSAtsushi Murai   case ST_STARTING:
373927145beSBrian Somers     LogPrintf(LogLCP, "Oops, RCR in %s.\n", StateNames[fp->state]);
374af57ed9fSAtsushi Murai     pfree(bp);
375af57ed9fSAtsushi Murai     return;
376af57ed9fSAtsushi Murai   case ST_CLOSED:
377af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
378af57ed9fSAtsushi Murai     pfree(bp);
379af57ed9fSAtsushi Murai     return;
380af57ed9fSAtsushi Murai   case ST_CLOSING:
381af57ed9fSAtsushi Murai   case ST_STOPPING:
382927145beSBrian Somers     LogPrintf(LogERROR, "Got ConfigReq while state = %d\n", fp->state);
383af57ed9fSAtsushi Murai     pfree(bp);
384af57ed9fSAtsushi Murai     return;
385af57ed9fSAtsushi Murai   }
386af57ed9fSAtsushi Murai 
38753c9f6c0SAtsushi Murai   (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_REQ);
388af57ed9fSAtsushi Murai 
389af57ed9fSAtsushi Murai   if (nakp == NakBuff && rejp == RejBuff)
390af57ed9fSAtsushi Murai     ackaction = 1;
391af57ed9fSAtsushi Murai 
392af57ed9fSAtsushi Murai   switch (fp->state) {
393af57ed9fSAtsushi Murai   case ST_OPENED:
394af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
395af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
396af57ed9fSAtsushi Murai     break;
397af57ed9fSAtsushi Murai   case ST_STOPPED:
398af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
399af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
400af57ed9fSAtsushi Murai     break;
401af57ed9fSAtsushi Murai   }
402af57ed9fSAtsushi Murai 
403af57ed9fSAtsushi Murai   if (rejp != RejBuff)
404af57ed9fSAtsushi Murai     FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff);
405af57ed9fSAtsushi Murai   if (nakp != NakBuff)
406af57ed9fSAtsushi Murai     FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff);
407af57ed9fSAtsushi Murai   if (ackaction)
408af57ed9fSAtsushi Murai     FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff);
409af57ed9fSAtsushi Murai 
410af57ed9fSAtsushi Murai   switch (fp->state) {
411af57ed9fSAtsushi Murai   case ST_STOPPED:
412af57ed9fSAtsushi Murai   case ST_OPENED:
413af57ed9fSAtsushi Murai     if (ackaction)
414af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
415af57ed9fSAtsushi Murai     else
416af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
417af57ed9fSAtsushi Murai     break;
418af57ed9fSAtsushi Murai   case ST_REQSENT:
419af57ed9fSAtsushi Murai     if (ackaction)
420af57ed9fSAtsushi Murai       NewState(fp, ST_ACKSENT);
421af57ed9fSAtsushi Murai     break;
422af57ed9fSAtsushi Murai   case ST_ACKRCVD:
423af57ed9fSAtsushi Murai     if (ackaction) {
424af57ed9fSAtsushi Murai       NewState(fp, ST_OPENED);
425af57ed9fSAtsushi Murai       (fp->LayerUp)(fp);
426af57ed9fSAtsushi Murai     }
427af57ed9fSAtsushi Murai     break;
428af57ed9fSAtsushi Murai   case ST_ACKSENT:
429af57ed9fSAtsushi Murai     if (!ackaction)
430af57ed9fSAtsushi Murai       NewState(fp, ST_REQSENT);
431af57ed9fSAtsushi Murai     break;
432af57ed9fSAtsushi Murai   }
433af57ed9fSAtsushi Murai   pfree(bp);
434af57ed9fSAtsushi Murai }
435af57ed9fSAtsushi Murai 
436af57ed9fSAtsushi Murai void
437af57ed9fSAtsushi Murai FsmRecvConfigAck(fp, lhp, bp)			/* RCA */
438af57ed9fSAtsushi Murai struct fsm *fp;
439af57ed9fSAtsushi Murai struct fsmheader *lhp;
440af57ed9fSAtsushi Murai struct mbuf *bp;
441af57ed9fSAtsushi Murai {
442af57ed9fSAtsushi Murai   switch (fp->state) {
443af57ed9fSAtsushi Murai   case ST_CLOSED:
444af57ed9fSAtsushi Murai   case ST_STOPPED:
445af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
446af57ed9fSAtsushi Murai     break;
447af57ed9fSAtsushi Murai   case ST_CLOSING:
448af57ed9fSAtsushi Murai   case ST_STOPPING:
449af57ed9fSAtsushi Murai     break;
450af57ed9fSAtsushi Murai   case ST_REQSENT:
451af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
452af57ed9fSAtsushi Murai     NewState(fp, ST_ACKRCVD);
453af57ed9fSAtsushi Murai     break;
454af57ed9fSAtsushi Murai   case ST_ACKRCVD:
455af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
456af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
457af57ed9fSAtsushi Murai     break;
458af57ed9fSAtsushi Murai   case ST_ACKSENT:
459af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
460af57ed9fSAtsushi Murai     NewState(fp, ST_OPENED);
461af57ed9fSAtsushi Murai     (fp->LayerUp)(fp);
462af57ed9fSAtsushi Murai     break;
463af57ed9fSAtsushi Murai   case ST_OPENED:
464af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
465af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
466af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
467af57ed9fSAtsushi Murai     break;
468af57ed9fSAtsushi Murai   }
469af57ed9fSAtsushi Murai   pfree(bp);
470af57ed9fSAtsushi Murai }
471af57ed9fSAtsushi Murai 
472af57ed9fSAtsushi Murai void
473af57ed9fSAtsushi Murai FsmRecvConfigNak(fp, lhp, bp)			/* RCN */
474af57ed9fSAtsushi Murai struct fsm *fp;
475af57ed9fSAtsushi Murai struct fsmheader *lhp;
476af57ed9fSAtsushi Murai struct mbuf *bp;
477af57ed9fSAtsushi Murai {
47853c9f6c0SAtsushi Murai   int plen, flen;
479af57ed9fSAtsushi Murai 
480af57ed9fSAtsushi Murai   plen = plength(bp);
48153c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
48253c9f6c0SAtsushi Murai   if (plen < flen) {
483af57ed9fSAtsushi Murai     pfree(bp);
484af57ed9fSAtsushi Murai     return;
485af57ed9fSAtsushi Murai   }
486af57ed9fSAtsushi Murai 
487af57ed9fSAtsushi Murai   /*
488af57ed9fSAtsushi Murai    *  Check and process easy case
489af57ed9fSAtsushi Murai    */
490af57ed9fSAtsushi Murai   switch (fp->state) {
491af57ed9fSAtsushi Murai   case ST_INITIAL:
492af57ed9fSAtsushi Murai   case ST_STARTING:
493927145beSBrian Somers     LogPrintf(LogLCP, "Oops, RCN in %s.\n", StateNames[fp->state]);
494af57ed9fSAtsushi Murai     pfree(bp);
495af57ed9fSAtsushi Murai     return;
496af57ed9fSAtsushi Murai   case ST_CLOSED:
497af57ed9fSAtsushi Murai   case ST_STOPPED:
498af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
499af57ed9fSAtsushi Murai     pfree(bp);
500af57ed9fSAtsushi Murai     return;
501af57ed9fSAtsushi Murai   case ST_CLOSING:
502af57ed9fSAtsushi Murai   case ST_STOPPING:
503af57ed9fSAtsushi Murai     pfree(bp);
504af57ed9fSAtsushi Murai     return;
505af57ed9fSAtsushi Murai   }
506af57ed9fSAtsushi Murai 
50753c9f6c0SAtsushi Murai   (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_NAK);
508af57ed9fSAtsushi Murai 
509af57ed9fSAtsushi Murai   switch (fp->state) {
510af57ed9fSAtsushi Murai   case ST_REQSENT:
511af57ed9fSAtsushi Murai   case ST_ACKSENT:
512af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
513af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
514af57ed9fSAtsushi Murai     break;
515af57ed9fSAtsushi Murai   case ST_OPENED:
516af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
517af57ed9fSAtsushi Murai     /* Fall down */
518af57ed9fSAtsushi Murai   case ST_ACKRCVD:
519af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
520af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
521af57ed9fSAtsushi Murai     break;
522af57ed9fSAtsushi Murai   }
523af57ed9fSAtsushi Murai 
524af57ed9fSAtsushi Murai   pfree(bp);
525af57ed9fSAtsushi Murai }
526af57ed9fSAtsushi Murai 
527af57ed9fSAtsushi Murai void
528af57ed9fSAtsushi Murai FsmRecvTermReq(fp, lhp, bp)				/* RTR */
529af57ed9fSAtsushi Murai struct fsm *fp;
530af57ed9fSAtsushi Murai struct fsmheader *lhp;
531af57ed9fSAtsushi Murai struct mbuf *bp;
532af57ed9fSAtsushi Murai {
533af57ed9fSAtsushi Murai   switch (fp->state) {
534af57ed9fSAtsushi Murai   case ST_INITIAL:
535af57ed9fSAtsushi Murai   case ST_STARTING:
536927145beSBrian Somers     LogPrintf(LogLCP, "Oops, RTR in %s\n", StateNames[fp->state]);
537af57ed9fSAtsushi Murai     break;
538af57ed9fSAtsushi Murai   case ST_CLOSED:
539af57ed9fSAtsushi Murai   case ST_STOPPED:
540af57ed9fSAtsushi Murai   case ST_CLOSING:
541af57ed9fSAtsushi Murai   case ST_STOPPING:
542af57ed9fSAtsushi Murai   case ST_REQSENT:
543af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
544af57ed9fSAtsushi Murai     break;
545af57ed9fSAtsushi Murai   case ST_ACKRCVD:
546af57ed9fSAtsushi Murai   case ST_ACKSENT:
547af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
548af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
549af57ed9fSAtsushi Murai     break;
550af57ed9fSAtsushi Murai   case ST_OPENED:
5518f2fa0eeSBrian Somers     (fp->LayerDown)(fp);
552af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
5538f2fa0eeSBrian Somers     StartTimer(&fp->FsmTimer);	/* Start restart timer */
5548f2fa0eeSBrian Somers     fp->restart = 0;
5558f2fa0eeSBrian Somers     NewState(fp, ST_STOPPING);
556af57ed9fSAtsushi Murai     break;
557af57ed9fSAtsushi Murai   }
558af57ed9fSAtsushi Murai   pfree(bp);
559af57ed9fSAtsushi Murai }
560af57ed9fSAtsushi Murai 
561af57ed9fSAtsushi Murai void
562af57ed9fSAtsushi Murai FsmRecvTermAck(fp, lhp, bp)			/* RTA */
563af57ed9fSAtsushi Murai struct fsm *fp;
564af57ed9fSAtsushi Murai struct fsmheader *lhp;
565af57ed9fSAtsushi Murai struct mbuf *bp;
566af57ed9fSAtsushi Murai {
567af57ed9fSAtsushi Murai   switch (fp->state) {
568af57ed9fSAtsushi Murai   case ST_CLOSING:
569af57ed9fSAtsushi Murai     NewState(fp, ST_CLOSED);
570af57ed9fSAtsushi Murai     (fp->LayerFinish)(fp);
571af57ed9fSAtsushi Murai     break;
572af57ed9fSAtsushi Murai   case ST_STOPPING:
573af57ed9fSAtsushi Murai     NewState(fp, ST_STOPPED);
574af57ed9fSAtsushi Murai     (fp->LayerFinish)(fp);
575af57ed9fSAtsushi Murai     break;
576af57ed9fSAtsushi Murai   case ST_ACKRCVD:
577af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
578af57ed9fSAtsushi Murai     break;
579af57ed9fSAtsushi Murai   case ST_OPENED:
580af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
581af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
582af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
583af57ed9fSAtsushi Murai     break;
584af57ed9fSAtsushi Murai   }
585af57ed9fSAtsushi Murai   pfree(bp);
586af57ed9fSAtsushi Murai }
587af57ed9fSAtsushi Murai 
588af57ed9fSAtsushi Murai void
589af57ed9fSAtsushi Murai FsmRecvConfigRej(fp, lhp, bp)			/* RCJ */
590af57ed9fSAtsushi Murai struct fsm *fp;
591af57ed9fSAtsushi Murai struct fsmheader *lhp;
592af57ed9fSAtsushi Murai struct mbuf *bp;
593af57ed9fSAtsushi Murai {
59453c9f6c0SAtsushi Murai   int plen, flen;
595af57ed9fSAtsushi Murai 
596af57ed9fSAtsushi Murai   plen = plength(bp);
59753c9f6c0SAtsushi Murai   flen = ntohs(lhp->length) - sizeof(*lhp);
59853c9f6c0SAtsushi Murai   if (plen < flen) {
599af57ed9fSAtsushi Murai     pfree(bp);
600af57ed9fSAtsushi Murai     return;
601af57ed9fSAtsushi Murai   }
602927145beSBrian Somers   LogPrintf(LogLCP, "RecvConfigRej.\n");
603af57ed9fSAtsushi Murai 
604af57ed9fSAtsushi Murai   /*
605af57ed9fSAtsushi Murai    *  Check and process easy case
606af57ed9fSAtsushi Murai    */
607af57ed9fSAtsushi Murai   switch (fp->state) {
608af57ed9fSAtsushi Murai   case ST_INITIAL:
609af57ed9fSAtsushi Murai   case ST_STARTING:
610927145beSBrian Somers     LogPrintf(LogLCP, "Oops, RCJ in %s.\n", StateNames[fp->state]);
611af57ed9fSAtsushi Murai     pfree(bp);
612af57ed9fSAtsushi Murai     return;
613af57ed9fSAtsushi Murai   case ST_CLOSED:
614af57ed9fSAtsushi Murai   case ST_STOPPED:
615af57ed9fSAtsushi Murai     (fp->SendTerminateAck)(fp);
616af57ed9fSAtsushi Murai     pfree(bp);
617af57ed9fSAtsushi Murai     return;
618af57ed9fSAtsushi Murai   case ST_CLOSING:
619af57ed9fSAtsushi Murai   case ST_STOPPING:
620af57ed9fSAtsushi Murai     pfree(bp);
621af57ed9fSAtsushi Murai     return;
622af57ed9fSAtsushi Murai   }
623af57ed9fSAtsushi Murai 
62453c9f6c0SAtsushi Murai   (fp->DecodeConfig)(MBUF_CTOP(bp), flen, MODE_REJ);
625af57ed9fSAtsushi Murai 
626af57ed9fSAtsushi Murai   switch (fp->state) {
627af57ed9fSAtsushi Murai   case ST_REQSENT:
628af57ed9fSAtsushi Murai   case ST_ACKSENT:
629af57ed9fSAtsushi Murai     FsmInitRestartCounter(fp);
630af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
631af57ed9fSAtsushi Murai     break;
632af57ed9fSAtsushi Murai   case ST_OPENED:
633af57ed9fSAtsushi Murai     (fp->LayerDown)(fp);
634af57ed9fSAtsushi Murai     /* Fall down */
635af57ed9fSAtsushi Murai   case ST_ACKRCVD:
636af57ed9fSAtsushi Murai     FsmSendConfigReq(fp);
637af57ed9fSAtsushi Murai     NewState(fp, ST_REQSENT);
638af57ed9fSAtsushi Murai     break;
639af57ed9fSAtsushi Murai   }
640af57ed9fSAtsushi Murai   pfree(bp);
641af57ed9fSAtsushi Murai }
642af57ed9fSAtsushi Murai 
643af57ed9fSAtsushi Murai void
644af57ed9fSAtsushi Murai FsmRecvCodeRej(fp, lhp, bp)
645af57ed9fSAtsushi Murai struct fsm *fp;
646af57ed9fSAtsushi Murai struct fsmheader *lhp;
647af57ed9fSAtsushi Murai struct mbuf *bp;
648af57ed9fSAtsushi Murai {
649927145beSBrian Somers   LogPrintf(LogLCP, "RecvCodeRej\n");
650af57ed9fSAtsushi Murai   pfree(bp);
651af57ed9fSAtsushi Murai }
652af57ed9fSAtsushi Murai 
653af57ed9fSAtsushi Murai void
654af57ed9fSAtsushi Murai FsmRecvProtoRej(fp, lhp, bp)
655af57ed9fSAtsushi Murai struct fsm *fp;
656af57ed9fSAtsushi Murai struct fsmheader *lhp;
657af57ed9fSAtsushi Murai struct mbuf *bp;
658af57ed9fSAtsushi Murai {
659af57ed9fSAtsushi Murai   u_short *sp, proto;
660af57ed9fSAtsushi Murai 
661af57ed9fSAtsushi Murai   sp = (u_short *)MBUF_CTOP(bp);
662af57ed9fSAtsushi Murai   proto = ntohs(*sp);
663927145beSBrian Somers   LogPrintf(LogLCP, "-- Protocol (%04x) was rejected.\n", proto);
664af57ed9fSAtsushi Murai 
665af57ed9fSAtsushi Murai   switch (proto) {
666af57ed9fSAtsushi Murai   case PROTO_LQR:
667af57ed9fSAtsushi Murai     StopLqr(LQM_LQR);
668af57ed9fSAtsushi Murai     break;
669af57ed9fSAtsushi Murai   case PROTO_CCP:
670af57ed9fSAtsushi Murai     fp = &CcpFsm;
671af57ed9fSAtsushi Murai     (fp->LayerFinish)(fp);
672af57ed9fSAtsushi Murai     switch (fp->state) {
673af57ed9fSAtsushi Murai     case ST_CLOSED:
674af57ed9fSAtsushi Murai     case ST_CLOSING:
675af57ed9fSAtsushi Murai       NewState(fp, ST_CLOSED);
676af57ed9fSAtsushi Murai     default:
677af57ed9fSAtsushi Murai       NewState(fp, ST_STOPPED);
678af57ed9fSAtsushi Murai       break;
679af57ed9fSAtsushi Murai     }
680af57ed9fSAtsushi Murai     break;
681af57ed9fSAtsushi Murai   }
682af57ed9fSAtsushi Murai   pfree(bp);
683af57ed9fSAtsushi Murai }
684af57ed9fSAtsushi Murai 
685af57ed9fSAtsushi Murai void
686af57ed9fSAtsushi Murai FsmRecvEchoReq(fp, lhp, bp)
687af57ed9fSAtsushi Murai struct fsm *fp;
688af57ed9fSAtsushi Murai struct fsmheader *lhp;
689af57ed9fSAtsushi Murai struct mbuf *bp;
690af57ed9fSAtsushi Murai {
691af57ed9fSAtsushi Murai   u_char *cp;
692af57ed9fSAtsushi Murai   u_long *lp, magic;
693af57ed9fSAtsushi Murai 
694af57ed9fSAtsushi Murai   cp = MBUF_CTOP(bp);
695af57ed9fSAtsushi Murai   lp = (u_long *)cp;
696af57ed9fSAtsushi Murai   magic = ntohl(*lp);
697af57ed9fSAtsushi Murai   if (magic != LcpInfo.his_magic) {
698927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n");
699af57ed9fSAtsushi Murai     /* XXX: We should send terminate request */
700af57ed9fSAtsushi Murai   }
701af57ed9fSAtsushi Murai 
702af57ed9fSAtsushi Murai   if (fp->state == ST_OPENED) {
703af57ed9fSAtsushi Murai     *lp = htonl(LcpInfo.want_magic);	/* Insert local magic number */
704927145beSBrian Somers     LogPrintf(LogLCP, "SendEchoRep(%s)\n", StateNames[fp->state]);
705af57ed9fSAtsushi Murai     FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp));
706af57ed9fSAtsushi Murai   }
707af57ed9fSAtsushi Murai   pfree(bp);
708af57ed9fSAtsushi Murai }
709af57ed9fSAtsushi Murai 
710af57ed9fSAtsushi Murai void
711af57ed9fSAtsushi Murai FsmRecvEchoRep(fp, lhp, bp)
712af57ed9fSAtsushi Murai struct fsm *fp;
713af57ed9fSAtsushi Murai struct fsmheader *lhp;
714af57ed9fSAtsushi Murai struct mbuf *bp;
715af57ed9fSAtsushi Murai {
716af57ed9fSAtsushi Murai   u_long *lp, magic;
717af57ed9fSAtsushi Murai 
718af57ed9fSAtsushi Murai   lp = (u_long *)MBUF_CTOP(bp);
719af57ed9fSAtsushi Murai   magic = ntohl(*lp);
72085c59f05SJoerg Wunsch /*
72185c59f05SJoerg Wunsch  * Tolerate echo replies with either magic number
72285c59f05SJoerg Wunsch  */
72385c59f05SJoerg Wunsch   if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) {
724927145beSBrian Somers     LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n",
725af57ed9fSAtsushi Murai 	LcpInfo.his_magic, magic);
726af57ed9fSAtsushi Murai     /*
727af57ed9fSAtsushi Murai      *  XXX: We should send terminate request. But poor implementation
728af57ed9fSAtsushi Murai      *       may die as a result.
729af57ed9fSAtsushi Murai      */
730af57ed9fSAtsushi Murai   }
731af57ed9fSAtsushi Murai   RecvEchoLqr(bp);
732af57ed9fSAtsushi Murai   pfree(bp);
733af57ed9fSAtsushi Murai }
734af57ed9fSAtsushi Murai 
735af57ed9fSAtsushi Murai void
736af57ed9fSAtsushi Murai FsmRecvDiscReq(fp, lhp, bp)
737af57ed9fSAtsushi Murai struct fsm *fp;
738af57ed9fSAtsushi Murai struct fsmheader *lhp;
739af57ed9fSAtsushi Murai struct mbuf *bp;
740af57ed9fSAtsushi Murai {
741927145beSBrian Somers   LogPrintf(LogLCP, "RecvDiscReq\n");
742af57ed9fSAtsushi Murai   pfree(bp);
743af57ed9fSAtsushi Murai }
744af57ed9fSAtsushi Murai 
745af57ed9fSAtsushi Murai void
746af57ed9fSAtsushi Murai FsmRecvIdent(fp, lhp, bp)
747af57ed9fSAtsushi Murai struct fsm *fp;
748af57ed9fSAtsushi Murai struct fsmheader *lhp;
749af57ed9fSAtsushi Murai struct mbuf *bp;
750af57ed9fSAtsushi Murai {
751927145beSBrian Somers   LogPrintf(LogLCP, "RecvIdent\n");
752af57ed9fSAtsushi Murai   pfree(bp);
753af57ed9fSAtsushi Murai }
754af57ed9fSAtsushi Murai 
755af57ed9fSAtsushi Murai void
756af57ed9fSAtsushi Murai FsmRecvTimeRemain(fp, lhp, bp)
757af57ed9fSAtsushi Murai struct fsm *fp;
758af57ed9fSAtsushi Murai struct fsmheader *lhp;
759af57ed9fSAtsushi Murai struct mbuf *bp;
760af57ed9fSAtsushi Murai {
761927145beSBrian Somers   LogPrintf(LogLCP, "RecvTimeRemain\n");
762af57ed9fSAtsushi Murai   pfree(bp);
763af57ed9fSAtsushi Murai }
764af57ed9fSAtsushi Murai 
765af57ed9fSAtsushi Murai void
766af57ed9fSAtsushi Murai FsmRecvResetReq(fp, lhp, bp)
767af57ed9fSAtsushi Murai struct fsm *fp;
768af57ed9fSAtsushi Murai struct fsmheader *lhp;
769af57ed9fSAtsushi Murai struct mbuf *bp;
770af57ed9fSAtsushi Murai {
771927145beSBrian Somers   LogPrintf(LogLCP, "RecvResetReq\n");
772af57ed9fSAtsushi Murai   CcpRecvResetReq(fp);
773927145beSBrian Somers   LogPrintf(LogLCP, "SendResetAck\n");
774af57ed9fSAtsushi Murai   FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0);
775af57ed9fSAtsushi Murai   pfree(bp);
776af57ed9fSAtsushi Murai }
777af57ed9fSAtsushi Murai 
778af57ed9fSAtsushi Murai void
779af57ed9fSAtsushi Murai FsmRecvResetAck(fp, lhp, bp)
780af57ed9fSAtsushi Murai struct fsm *fp;
781af57ed9fSAtsushi Murai struct fsmheader *lhp;
782af57ed9fSAtsushi Murai struct mbuf *bp;
783af57ed9fSAtsushi Murai {
784927145beSBrian Somers   LogPrintf(LogLCP, "RecvResetAck\n");
785af57ed9fSAtsushi Murai   fp->reqid++;
786af57ed9fSAtsushi Murai   pfree(bp);
787af57ed9fSAtsushi Murai }
788af57ed9fSAtsushi Murai 
789af57ed9fSAtsushi Murai struct fsmcodedesc FsmCodes[] = {
790af57ed9fSAtsushi Murai  { FsmRecvConfigReq,  "Configure Request", },
791af57ed9fSAtsushi Murai  { FsmRecvConfigAck,  "Configure Ack", },
792af57ed9fSAtsushi Murai  { FsmRecvConfigNak,  "Configure Nak", },
793af57ed9fSAtsushi Murai  { FsmRecvConfigRej,  "Configure Reject", },
794af57ed9fSAtsushi Murai  { FsmRecvTermReq,    "Terminate Request", },
795af57ed9fSAtsushi Murai  { FsmRecvTermAck,    "Terminate Ack", },
796af57ed9fSAtsushi Murai  { FsmRecvCodeRej,    "Code Reject", },
797af57ed9fSAtsushi Murai  { FsmRecvProtoRej,   "Protocol Reject", },
798af57ed9fSAtsushi Murai  { FsmRecvEchoReq,    "Echo Request", },
799af57ed9fSAtsushi Murai  { FsmRecvEchoRep,    "Echo Reply", },
800af57ed9fSAtsushi Murai  { FsmRecvDiscReq,    "Discard Request", },
801af57ed9fSAtsushi Murai  { FsmRecvIdent,      "Ident", },
802af57ed9fSAtsushi Murai  { FsmRecvTimeRemain, "Time Remain", },
803af57ed9fSAtsushi Murai  { FsmRecvResetReq,   "Reset Request", },
804af57ed9fSAtsushi Murai  { FsmRecvResetAck,   "Reset Ack", },
805af57ed9fSAtsushi Murai };
806af57ed9fSAtsushi Murai 
807af57ed9fSAtsushi Murai void
808af57ed9fSAtsushi Murai FsmInput(fp, bp)
809af57ed9fSAtsushi Murai struct fsm *fp;
810af57ed9fSAtsushi Murai struct mbuf *bp;
811af57ed9fSAtsushi Murai {
812af57ed9fSAtsushi Murai   int len;
813af57ed9fSAtsushi Murai   struct fsmheader *lhp;
814af57ed9fSAtsushi Murai   struct fsmcodedesc *codep;
815af57ed9fSAtsushi Murai 
816af57ed9fSAtsushi Murai   len = plength(bp);
817af57ed9fSAtsushi Murai   if (len < sizeof(struct fsmheader)) {
818af57ed9fSAtsushi Murai     pfree(bp);
819af57ed9fSAtsushi Murai     return;
820af57ed9fSAtsushi Murai   }
821af57ed9fSAtsushi Murai   lhp = (struct fsmheader *)MBUF_CTOP(bp);
822af57ed9fSAtsushi Murai   if (lhp->code == 0 || lhp->code > fp->max_code) {
823af57ed9fSAtsushi Murai     pfree(bp);		/* XXX: Should send code reject */
824af57ed9fSAtsushi Murai     return;
825af57ed9fSAtsushi Murai   }
826af57ed9fSAtsushi Murai 
827af57ed9fSAtsushi Murai   bp->offset += sizeof(struct fsmheader);
828af57ed9fSAtsushi Murai   bp->cnt -= sizeof(struct fsmheader);
829af57ed9fSAtsushi Murai 
830af57ed9fSAtsushi Murai   codep = FsmCodes + lhp->code - 1;
831927145beSBrian Somers   LogPrintf(LogLCP, "Received %s (%d) state = %s (%d)\n",
832927145beSBrian Somers     codep->name, lhp->id, StateNames[fp->state], fp->state);
833927145beSBrian Somers   if (LogIsKept(LogDEBUG))
834af57ed9fSAtsushi Murai     LogMemory();
835af57ed9fSAtsushi Murai   (codep->action)(fp, lhp, bp);
836927145beSBrian Somers   if (LogIsKept(LogDEBUG))
837af57ed9fSAtsushi Murai     LogMemory();
838af57ed9fSAtsushi Murai }
839