fsm.c revision 37210
1139823Simp/*
21541Srgrimes *		PPP Finite State Machine for LCP/IPCP
3180305Srwatson *
4180305Srwatson *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
51541Srgrimes *
61541Srgrimes *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms are permitted
91541Srgrimes * provided that the above copyright notice and this paragraph are
101541Srgrimes * duplicated in all such forms and that any documentation,
111541Srgrimes * advertising materials, and other materials related to such
121541Srgrimes * distribution and use acknowledge that the software was developed
131541Srgrimes * by the Internet Initiative Japan, Inc.  The name of the
141541Srgrimes * IIJ may not be used to endorse or promote products derived
151541Srgrimes * from this software without specific prior written permission.
161541Srgrimes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
171541Srgrimes * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
181541Srgrimes * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
191541Srgrimes *
201541Srgrimes * $Id: fsm.c,v 1.33 1998/06/25 22:33:20 brian Exp $
211541Srgrimes *
221541Srgrimes *  TODO:
231541Srgrimes */
241541Srgrimes
251541Srgrimes#include <sys/types.h>
261541Srgrimes#include <netinet/in.h>
271541Srgrimes#include <netinet/in_systm.h>
281541Srgrimes#include <netinet/ip.h>
291541Srgrimes#include <sys/un.h>
301541Srgrimes
3150477Speter#include <string.h>
321541Srgrimes#include <termios.h>
331541Srgrimes
341541Srgrimes#include "mbuf.h"
3596972Stanimura#include "log.h"
36130387Srwatson#include "defs.h"
37180390Srwatson#include "timer.h"
3829024Sbde#include "fsm.h"
39130387Srwatson#include "iplist.h"
4096972Stanimura#include "lqr.h"
411541Srgrimes#include "hdlc.h"
421541Srgrimes#include "throughput.h"
43180390Srwatson#include "slcompress.h"
4497093Sbde#include "ipcp.h"
451541Srgrimes#include "filter.h"
461541Srgrimes#include "descriptor.h"
471541Srgrimes#include "lcp.h"
481541Srgrimes#include "ccp.h"
498876Srgrimes#include "link.h"
501541Srgrimes#include "mp.h"
511541Srgrimes#include "bundle.h"
521541Srgrimes#include "async.h"
531541Srgrimes#include "physical.h"
541541Srgrimes#include "lcpproto.h"
551541Srgrimes
561541Srgrimesstatic void FsmSendConfigReq(struct fsm *);
57130514Srwatsonstatic void FsmSendTerminateReq(struct fsm *);
5824936Sphkstatic void FsmInitRestartCounter(struct fsm *);
5924936Sphk
60180390Srwatsontypedef void (recvfn)(struct fsm *, struct fsmheader *, struct mbuf *);
611541Srgrimesstatic recvfn FsmRecvConfigReq, FsmRecvConfigAck, FsmRecvConfigNak,
62180390Srwatson              FsmRecvConfigRej, FsmRecvTermReq, FsmRecvTermAck,
63180390Srwatson              FsmRecvCodeRej, FsmRecvProtoRej, FsmRecvEchoReq,
64180390Srwatson              FsmRecvEchoRep, FsmRecvDiscReq, FsmRecvIdent,
65180390Srwatson              FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck;
66180390Srwatson
67180390Srwatsonstatic const struct fsmcodedesc {
68180390Srwatson  recvfn *recv;
69180390Srwatson  unsigned check_reqid : 1;
701541Srgrimes  unsigned inc_reqid : 1;
71180305Srwatson  const char *name;
72180305Srwatson} FsmCodes[] = {
731541Srgrimes  { FsmRecvConfigReq, 0, 0, "ConfigReq"    },
741541Srgrimes  { FsmRecvConfigAck, 1, 1, "ConfigAck"    },
75180305Srwatson  { FsmRecvConfigNak, 1, 1, "ConfigNak"    },
761541Srgrimes  { FsmRecvConfigRej, 1, 1, "ConfigRej"    },
77180305Srwatson  { FsmRecvTermReq,   0, 0, "TerminateReq" },
781541Srgrimes  { FsmRecvTermAck,   1, 1, "TerminateAck" },
791541Srgrimes  { FsmRecvCodeRej,   0, 0, "CodeRej"      },
801541Srgrimes  { FsmRecvProtoRej,  0, 0, "ProtocolRej"  },
81180391Srwatson  { FsmRecvEchoReq,   0, 0, "EchoRequest"  },
82180391Srwatson  { FsmRecvEchoRep,   0, 0, "EchoReply"    },
83180391Srwatson  { FsmRecvDiscReq,   0, 0, "DiscardReq"   },
84180391Srwatson  { FsmRecvIdent,     0, 0, "Ident"        },
851541Srgrimes  { FsmRecvTimeRemain,0, 0, "TimeRemain"   },
86180391Srwatson  { FsmRecvResetReq,  0, 0, "ResetReqt"    },
87180391Srwatson  { FsmRecvResetAck,  0, 1, "ResetAck"     }
883443Sphk};
893443Sphk
901541Srgrimesstatic const char *
911541SrgrimesCode2Nam(u_int code)
921541Srgrimes{
931541Srgrimes  if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0])
94130514Srwatson    return "Unknown";
9524936Sphk  return FsmCodes[code-1].name;
96130514Srwatson}
971541Srgrimes
981541Srgrimesconst char *
991541SrgrimesState2Nam(u_int state)
1001541Srgrimes{
101180305Srwatson  static const char *StateNames[] = {
1021541Srgrimes    "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
1031541Srgrimes    "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
104180305Srwatson  };
1051541Srgrimes
1061541Srgrimes  if (state >= sizeof StateNames / sizeof StateNames[0])
1071541Srgrimes    return "unknown";
108157370Srwatson  return StateNames[state];
109157370Srwatson}
110157370Srwatson
111140775Srwatsonstatic void
11224936SphkStoppedTimeout(void *v)
113140775Srwatson{
1141541Srgrimes  struct fsm *fp = (struct fsm *)v;
1151541Srgrimes
116  log_Printf(fp->LogLevel, "%s: Stopped timer expired\n", fp->link->name);
117  if (fp->OpenTimer.state == TIMER_RUNNING) {
118    log_Printf(LogWARN, "%s: %s: aborting open delay due to stopped timer\n",
119              fp->link->name, fp->name);
120    timer_Stop(&fp->OpenTimer);
121  }
122  if (fp->state == ST_STOPPED)
123    fsm2initial(fp);
124}
125
126void
127fsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode,
128         int maxcode, int maxcfg, int LogLevel, struct bundle *bundle,
129         struct link *l, const struct fsm_parent *parent,
130         struct fsm_callbacks *fn, const char *timer_names[3])
131{
132  fp->name = name;
133  fp->proto = proto;
134  fp->min_code = mincode;
135  fp->max_code = maxcode;
136  fp->state = fp->min_code > CODE_TERMACK ? ST_OPENED : ST_INITIAL;
137  fp->reqid = 1;
138  fp->restart = 1;
139  fp->maxconfig = maxcfg;
140  memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer);
141  memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer);
142  memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer);
143  fp->LogLevel = LogLevel;
144  fp->link = l;
145  fp->bundle = bundle;
146  fp->parent = parent;
147  fp->fn = fn;
148  fp->FsmTimer.name = timer_names[0];
149  fp->OpenTimer.name = timer_names[1];
150  fp->StoppedTimer.name = timer_names[2];
151}
152
153static void
154NewState(struct fsm * fp, int new)
155{
156  log_Printf(fp->LogLevel, "%s: State change %s --> %s\n",
157	    fp->link->name, State2Nam(fp->state), State2Nam(new));
158  if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
159    timer_Stop(&fp->StoppedTimer);
160  fp->state = new;
161  if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
162    timer_Stop(&fp->FsmTimer);
163    if (new == ST_STOPPED && fp->StoppedTimer.load) {
164      timer_Stop(&fp->StoppedTimer);
165      fp->StoppedTimer.func = StoppedTimeout;
166      fp->StoppedTimer.arg = (void *) fp;
167      timer_Start(&fp->StoppedTimer);
168    }
169  }
170}
171
172void
173fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count)
174{
175  int plen;
176  struct fsmheader lh;
177  struct mbuf *bp;
178
179  if (log_IsKept(fp->LogLevel)) {
180    log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n",
181              fp->link->name, Code2Nam(code), id, State2Nam(fp->state));
182    switch (code) {
183      case CODE_CONFIGREQ:
184      case CODE_CONFIGACK:
185      case CODE_CONFIGREJ:
186      case CODE_CONFIGNAK:
187        (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL);
188        if (count < sizeof(struct fsmconfig))
189          log_Printf(fp->LogLevel, "  [EMPTY]\n");
190        break;
191    }
192  }
193
194  plen = sizeof(struct fsmheader) + count;
195  lh.code = code;
196  lh.id = id;
197  lh.length = htons(plen);
198  bp = mbuf_Alloc(plen, MB_FSM);
199  memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
200  if (count)
201    memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
202  log_DumpBp(LogDEBUG, "fsm_Output", bp);
203  hdlc_Output(fp->link, PRI_LINK, fp->proto, bp);
204}
205
206static void
207FsmOpenNow(void *v)
208{
209  struct fsm *fp = (struct fsm *)v;
210
211  timer_Stop(&fp->OpenTimer);
212  if (fp->state <= ST_STOPPED) {
213    if (fp->state != ST_STARTING) {
214      /*
215       * In practice, we're only here in ST_STOPPED (when delaying the
216       * first config request) or ST_CLOSED (when openmode == 0).
217       *
218       * The ST_STOPPED bit is breaking the RFC already :-(
219       *
220       * According to the RFC (1661) state transition table, a TLS isn't
221       * required for an Open event when state == Closed, but the RFC
222       * must be wrong as TLS hasn't yet been called (since the last TLF)
223       * ie, Initial gets an `Up' event, Closing gets a RTA etc.
224       */
225      (*fp->fn->LayerStart)(fp);
226      (*fp->parent->LayerStart)(fp->parent->object, fp);
227    }
228    FsmInitRestartCounter(fp);
229    FsmSendConfigReq(fp);
230    NewState(fp, ST_REQSENT);
231  }
232}
233
234void
235fsm_Open(struct fsm * fp)
236{
237  switch (fp->state) {
238  case ST_INITIAL:
239    NewState(fp, ST_STARTING);
240    (*fp->fn->LayerStart)(fp);
241    (*fp->parent->LayerStart)(fp->parent->object, fp);
242    break;
243  case ST_CLOSED:
244    if (fp->open_mode == OPEN_PASSIVE) {
245      NewState(fp, ST_STOPPED);		/* XXX: This is a hack ! */
246    } else if (fp->open_mode > 0) {
247      if (fp->open_mode > 1)
248        log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n",
249                  fp->link->name, fp->open_mode);
250      NewState(fp, ST_STOPPED);		/* XXX: This is a not-so-bad hack ! */
251      timer_Stop(&fp->OpenTimer);
252      fp->OpenTimer.load = fp->open_mode * SECTICKS;
253      fp->OpenTimer.func = FsmOpenNow;
254      fp->OpenTimer.arg = (void *)fp;
255      timer_Start(&fp->OpenTimer);
256    } else
257      FsmOpenNow(fp);
258    break;
259  case ST_STOPPED:		/* XXX: restart option */
260  case ST_REQSENT:
261  case ST_ACKRCVD:
262  case ST_ACKSENT:
263  case ST_OPENED:		/* XXX: restart option */
264    break;
265  case ST_CLOSING:		/* XXX: restart option */
266  case ST_STOPPING:		/* XXX: restart option */
267    NewState(fp, ST_STOPPING);
268    break;
269  }
270}
271
272void
273fsm_Up(struct fsm * fp)
274{
275  switch (fp->state) {
276  case ST_INITIAL:
277    log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n",
278              fp->link->name);
279    NewState(fp, ST_CLOSED);
280    break;
281  case ST_STARTING:
282    FsmInitRestartCounter(fp);
283    FsmSendConfigReq(fp);
284    NewState(fp, ST_REQSENT);
285    break;
286  default:
287    log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n",
288              fp->link->name, State2Nam(fp->state));
289    break;
290  }
291}
292
293void
294fsm_Down(struct fsm *fp)
295{
296  switch (fp->state) {
297  case ST_CLOSED:
298    NewState(fp, ST_INITIAL);
299    break;
300  case ST_CLOSING:
301    (*fp->fn->LayerFinish)(fp);
302    NewState(fp, ST_INITIAL);
303    (*fp->parent->LayerFinish)(fp->parent->object, fp);
304    break;
305  case ST_STOPPED:
306    NewState(fp, ST_STARTING);
307    (*fp->fn->LayerStart)(fp);
308    (*fp->parent->LayerStart)(fp->parent->object, fp);
309    break;
310  case ST_STOPPING:
311  case ST_REQSENT:
312  case ST_ACKRCVD:
313  case ST_ACKSENT:
314    NewState(fp, ST_STARTING);
315    break;
316  case ST_OPENED:
317    (*fp->fn->LayerDown)(fp);
318    NewState(fp, ST_STARTING);
319    (*fp->parent->LayerDown)(fp->parent->object, fp);
320    break;
321  }
322}
323
324void
325fsm_Close(struct fsm *fp)
326{
327  switch (fp->state) {
328  case ST_STARTING:
329    (*fp->fn->LayerFinish)(fp);
330    NewState(fp, ST_INITIAL);
331    (*fp->parent->LayerFinish)(fp->parent->object, fp);
332    break;
333  case ST_STOPPED:
334    NewState(fp, ST_CLOSED);
335    break;
336  case ST_STOPPING:
337    NewState(fp, ST_CLOSING);
338    break;
339  case ST_OPENED:
340    (*fp->fn->LayerDown)(fp);
341    FsmInitRestartCounter(fp);
342    FsmSendTerminateReq(fp);
343    NewState(fp, ST_CLOSING);
344    (*fp->parent->LayerDown)(fp->parent->object, fp);
345    break;
346  case ST_REQSENT:
347  case ST_ACKRCVD:
348  case ST_ACKSENT:
349    FsmInitRestartCounter(fp);
350    FsmSendTerminateReq(fp);
351    NewState(fp, ST_CLOSING);
352    break;
353  }
354}
355
356/*
357 *	Send functions
358 */
359static void
360FsmSendConfigReq(struct fsm * fp)
361{
362  if (--fp->maxconfig > 0) {
363    (*fp->fn->SendConfigReq)(fp);
364    timer_Start(&fp->FsmTimer);	/* Start restart timer */
365    fp->restart--;		/* Decrement restart counter */
366  } else {
367    fsm_Close(fp);
368  }
369}
370
371static void
372FsmSendTerminateReq(struct fsm *fp)
373{
374  fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0);
375  (*fp->fn->SentTerminateReq)(fp);
376  timer_Start(&fp->FsmTimer);	/* Start restart timer */
377  fp->restart--;		/* Decrement restart counter */
378}
379
380/*
381 *	Timeout actions
382 */
383static void
384FsmTimeout(void *v)
385{
386  struct fsm *fp = (struct fsm *)v;
387
388  if (fp->restart) {
389    switch (fp->state) {
390    case ST_CLOSING:
391    case ST_STOPPING:
392      FsmSendTerminateReq(fp);
393      break;
394    case ST_REQSENT:
395    case ST_ACKSENT:
396      FsmSendConfigReq(fp);
397      break;
398    case ST_ACKRCVD:
399      FsmSendConfigReq(fp);
400      NewState(fp, ST_REQSENT);
401      break;
402    }
403    timer_Start(&fp->FsmTimer);
404  } else {
405    switch (fp->state) {
406    case ST_CLOSING:
407      (*fp->fn->LayerFinish)(fp);
408      NewState(fp, ST_CLOSED);
409      (*fp->parent->LayerFinish)(fp->parent->object, fp);
410      break;
411    case ST_STOPPING:
412      (*fp->fn->LayerFinish)(fp);
413      NewState(fp, ST_STOPPED);
414      (*fp->parent->LayerFinish)(fp->parent->object, fp);
415      break;
416    case ST_REQSENT:		/* XXX: 3p */
417    case ST_ACKSENT:
418    case ST_ACKRCVD:
419      (*fp->fn->LayerFinish)(fp);
420      NewState(fp, ST_STOPPED);
421      (*fp->parent->LayerFinish)(fp->parent->object, fp);
422      break;
423    }
424  }
425}
426
427static void
428FsmInitRestartCounter(struct fsm * fp)
429{
430  timer_Stop(&fp->FsmTimer);
431  fp->FsmTimer.func = FsmTimeout;
432  fp->FsmTimer.arg = (void *) fp;
433  (*fp->fn->InitRestartCounter)(fp);
434}
435
436/*
437 *   Actions when receive packets
438 */
439static void
440FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
441/* RCR */
442{
443  struct fsm_decode dec;
444  int plen, flen;
445  int ackaction = 0;
446
447  plen = mbuf_Length(bp);
448  flen = ntohs(lhp->length) - sizeof *lhp;
449  if (plen < flen) {
450    log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",
451	      fp->link->name, plen, flen);
452    mbuf_Free(bp);
453    return;
454  }
455
456  /*
457   * Check and process easy case
458   */
459  switch (fp->state) {
460  case ST_INITIAL:
461  case ST_STARTING:
462    log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n",
463              fp->link->name, State2Nam(fp->state));
464    mbuf_Free(bp);
465    return;
466  case ST_CLOSED:
467    (*fp->fn->SendTerminateAck)(fp, lhp->id);
468    mbuf_Free(bp);
469    return;
470  case ST_CLOSING:
471    log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n",
472              fp->link->name, State2Nam(fp->state));
473  case ST_STOPPING:
474    mbuf_Free(bp);
475    return;
476  }
477
478  dec.ackend = dec.ack;
479  dec.nakend = dec.nak;
480  dec.rejend = dec.rej;
481  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec);
482  if (flen < sizeof(struct fsmconfig))
483    log_Printf(fp->LogLevel, "  [EMPTY]\n");
484
485  if (dec.nakend == dec.nak && dec.rejend == dec.rej)
486    ackaction = 1;
487
488  switch (fp->state) {
489  case ST_OPENED:
490    (*fp->fn->LayerDown)(fp);
491    FsmSendConfigReq(fp);
492    (*fp->parent->LayerDown)(fp->parent->object, fp);
493    break;
494  case ST_STOPPED:
495    FsmInitRestartCounter(fp);
496    FsmSendConfigReq(fp);
497    break;
498  }
499
500  if (dec.rejend != dec.rej)
501    fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej);
502  if (dec.nakend != dec.nak)
503    fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak);
504  if (ackaction)
505    fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack);
506
507  switch (fp->state) {
508  case ST_OPENED:
509  case ST_STOPPED:
510    if (ackaction)
511      NewState(fp, ST_ACKSENT);
512    else
513      NewState(fp, ST_REQSENT);
514    break;
515  case ST_REQSENT:
516    if (ackaction)
517      NewState(fp, ST_ACKSENT);
518    break;
519  case ST_ACKRCVD:
520    if (ackaction) {
521      NewState(fp, ST_OPENED);
522      if ((*fp->fn->LayerUp)(fp))
523        (*fp->parent->LayerUp)(fp->parent->object, fp);
524      else {
525        (*fp->fn->LayerDown)(fp);
526        FsmInitRestartCounter(fp);
527        FsmSendTerminateReq(fp);
528        NewState(fp, ST_CLOSING);
529      }
530    }
531    break;
532  case ST_ACKSENT:
533    if (!ackaction)
534      NewState(fp, ST_REQSENT);
535    break;
536  }
537  mbuf_Free(bp);
538}
539
540static void
541FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
542/* RCA */
543{
544  switch (fp->state) {
545    case ST_CLOSED:
546    case ST_STOPPED:
547    (*fp->fn->SendTerminateAck)(fp, lhp->id);
548    break;
549  case ST_CLOSING:
550  case ST_STOPPING:
551    break;
552  case ST_REQSENT:
553    FsmInitRestartCounter(fp);
554    NewState(fp, ST_ACKRCVD);
555    break;
556  case ST_ACKRCVD:
557    FsmSendConfigReq(fp);
558    NewState(fp, ST_REQSENT);
559    break;
560  case ST_ACKSENT:
561    FsmInitRestartCounter(fp);
562    NewState(fp, ST_OPENED);
563    if ((*fp->fn->LayerUp)(fp))
564      (*fp->parent->LayerUp)(fp->parent->object, fp);
565    else {
566      (*fp->fn->LayerDown)(fp);
567      FsmInitRestartCounter(fp);
568      FsmSendTerminateReq(fp);
569      NewState(fp, ST_CLOSING);
570    }
571    break;
572  case ST_OPENED:
573    (*fp->fn->LayerDown)(fp);
574    FsmSendConfigReq(fp);
575    NewState(fp, ST_REQSENT);
576    (*fp->parent->LayerDown)(fp->parent->object, fp);
577    break;
578  }
579  mbuf_Free(bp);
580}
581
582static void
583FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
584/* RCN */
585{
586  struct fsm_decode dec;
587  int plen, flen;
588
589  plen = mbuf_Length(bp);
590  flen = ntohs(lhp->length) - sizeof *lhp;
591  if (plen < flen) {
592    mbuf_Free(bp);
593    return;
594  }
595
596  /*
597   * Check and process easy case
598   */
599  switch (fp->state) {
600  case ST_INITIAL:
601  case ST_STARTING:
602    log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n",
603              fp->link->name, State2Nam(fp->state));
604    mbuf_Free(bp);
605    return;
606  case ST_CLOSED:
607  case ST_STOPPED:
608    (*fp->fn->SendTerminateAck)(fp, lhp->id);
609    mbuf_Free(bp);
610    return;
611  case ST_CLOSING:
612  case ST_STOPPING:
613    mbuf_Free(bp);
614    return;
615  }
616
617  dec.ackend = dec.ack;
618  dec.nakend = dec.nak;
619  dec.rejend = dec.rej;
620  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec);
621  if (flen < sizeof(struct fsmconfig))
622    log_Printf(fp->LogLevel, "  [EMPTY]\n");
623
624  switch (fp->state) {
625  case ST_REQSENT:
626  case ST_ACKSENT:
627    FsmInitRestartCounter(fp);
628    FsmSendConfigReq(fp);
629    break;
630  case ST_OPENED:
631    (*fp->fn->LayerDown)(fp);
632    FsmSendConfigReq(fp);
633    NewState(fp, ST_REQSENT);
634    (*fp->parent->LayerDown)(fp->parent->object, fp);
635    break;
636  case ST_ACKRCVD:
637    FsmSendConfigReq(fp);
638    NewState(fp, ST_REQSENT);
639    break;
640  }
641
642  mbuf_Free(bp);
643}
644
645static void
646FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
647/* RTR */
648{
649  switch (fp->state) {
650  case ST_INITIAL:
651  case ST_STARTING:
652    log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n",
653              fp->link->name, State2Nam(fp->state));
654    break;
655  case ST_CLOSED:
656  case ST_STOPPED:
657  case ST_CLOSING:
658  case ST_STOPPING:
659  case ST_REQSENT:
660    (*fp->fn->SendTerminateAck)(fp, lhp->id);
661    break;
662  case ST_ACKRCVD:
663  case ST_ACKSENT:
664    (*fp->fn->SendTerminateAck)(fp, lhp->id);
665    NewState(fp, ST_REQSENT);
666    break;
667  case ST_OPENED:
668    (*fp->fn->LayerDown)(fp);
669    (*fp->fn->SendTerminateAck)(fp, lhp->id);
670    FsmInitRestartCounter(fp);
671    timer_Start(&fp->FsmTimer);	/* Start restart timer */
672    fp->restart = 0;
673    NewState(fp, ST_STOPPING);
674    (*fp->parent->LayerDown)(fp->parent->object, fp);
675    break;
676  }
677  mbuf_Free(bp);
678}
679
680static void
681FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
682/* RTA */
683{
684  switch (fp->state) {
685  case ST_CLOSING:
686    (*fp->fn->LayerFinish)(fp);
687    NewState(fp, ST_CLOSED);
688    (*fp->parent->LayerFinish)(fp->parent->object, fp);
689    break;
690  case ST_STOPPING:
691    (*fp->fn->LayerFinish)(fp);
692    NewState(fp, ST_STOPPED);
693    (*fp->parent->LayerFinish)(fp->parent->object, fp);
694    break;
695  case ST_ACKRCVD:
696    NewState(fp, ST_REQSENT);
697    break;
698  case ST_OPENED:
699    (*fp->fn->LayerDown)(fp);
700    FsmSendConfigReq(fp);
701    NewState(fp, ST_REQSENT);
702    (*fp->parent->LayerDown)(fp->parent->object, fp);
703    break;
704  }
705  mbuf_Free(bp);
706}
707
708static void
709FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
710/* RCJ */
711{
712  struct fsm_decode dec;
713  int plen, flen;
714
715  plen = mbuf_Length(bp);
716  flen = ntohs(lhp->length) - sizeof *lhp;
717  if (plen < flen) {
718    mbuf_Free(bp);
719    return;
720  }
721
722  /*
723   * Check and process easy case
724   */
725  switch (fp->state) {
726  case ST_INITIAL:
727  case ST_STARTING:
728    log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n",
729              fp->link->name, State2Nam(fp->state));
730    mbuf_Free(bp);
731    return;
732  case ST_CLOSED:
733  case ST_STOPPED:
734    (*fp->fn->SendTerminateAck)(fp, lhp->id);
735    mbuf_Free(bp);
736    return;
737  case ST_CLOSING:
738  case ST_STOPPING:
739    mbuf_Free(bp);
740    return;
741  }
742
743  dec.ackend = dec.ack;
744  dec.nakend = dec.nak;
745  dec.rejend = dec.rej;
746  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec);
747  if (flen < sizeof(struct fsmconfig))
748    log_Printf(fp->LogLevel, "  [EMPTY]\n");
749
750  switch (fp->state) {
751  case ST_REQSENT:
752  case ST_ACKSENT:
753    FsmInitRestartCounter(fp);
754    FsmSendConfigReq(fp);
755    break;
756  case ST_OPENED:
757    (*fp->fn->LayerDown)(fp);
758    FsmSendConfigReq(fp);
759    NewState(fp, ST_REQSENT);
760    (*fp->parent->LayerDown)(fp->parent->object, fp);
761    break;
762  case ST_ACKRCVD:
763    FsmSendConfigReq(fp);
764    NewState(fp, ST_REQSENT);
765    break;
766  }
767  mbuf_Free(bp);
768}
769
770static void
771FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
772{
773  mbuf_Free(bp);
774}
775
776static void
777FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
778{
779  struct physical *p = link2physical(fp->link);
780  u_short *sp, proto;
781
782  sp = (u_short *)MBUF_CTOP(bp);
783  proto = ntohs(*sp);
784  log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n",
785            fp->link->name, proto, hdlc_Protocol2Nam(proto));
786
787  switch (proto) {
788  case PROTO_LQR:
789    if (p)
790      lqr_Stop(p, LQM_LQR);
791    else
792      log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n",
793                fp->link->name);
794    break;
795  case PROTO_CCP:
796    if (fp->proto == PROTO_LCP) {
797      fp = &fp->link->ccp.fsm;
798      (*fp->fn->LayerFinish)(fp);
799      switch (fp->state) {
800      case ST_CLOSED:
801      case ST_CLOSING:
802        NewState(fp, ST_CLOSED);
803      default:
804        NewState(fp, ST_STOPPED);
805        break;
806      }
807      (*fp->parent->LayerFinish)(fp->parent->object, fp);
808    }
809    break;
810  case PROTO_MP:
811    if (fp->proto == PROTO_LCP) {
812      struct lcp *lcp = fsm2lcp(fp);
813
814      if (lcp->want_mrru && lcp->his_mrru) {
815        log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n",
816                  fp->link->name);
817        fsm_Close(fp);
818      }
819    }
820    break;
821  }
822  mbuf_Free(bp);
823}
824
825static void
826FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
827{
828  struct lcp *lcp = fsm2lcp(fp);
829  u_char *cp;
830  u_int32_t magic;
831
832  if (lcp) {
833    cp = MBUF_CTOP(bp);
834    magic = ntohl(*(u_int32_t *)cp);
835    if (magic != lcp->his_magic) {
836      log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n",
837                fp->link->name);
838      /* XXX: We should send terminate request */
839    }
840    if (fp->state == ST_OPENED) {
841      *(u_int32_t *)cp = htonl(lcp->want_magic); /* local magic */
842      fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp));
843    }
844  }
845  mbuf_Free(bp);
846}
847
848static void
849FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
850{
851  struct lcp *lcp = fsm2lcp(fp);
852  u_int32_t magic;
853
854  if (lcp) {
855    magic = ntohl(*(u_int32_t *)MBUF_CTOP(bp));
856    /* Tolerate echo replies with either magic number */
857    if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) {
858      log_Printf(LogWARN,
859                "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n",
860	        fp->link->name, lcp->his_magic, magic);
861      /*
862       * XXX: We should send terminate request. But poor implementations may
863       * die as a result.
864       */
865    }
866    lqr_RecvEcho(fp, bp);
867  }
868  mbuf_Free(bp);
869}
870
871static void
872FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
873{
874  mbuf_Free(bp);
875}
876
877static void
878FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
879{
880  mbuf_Free(bp);
881}
882
883static void
884FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
885{
886  mbuf_Free(bp);
887}
888
889static void
890FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
891{
892  (*fp->fn->RecvResetReq)(fp);
893  /*
894   * All sendable compressed packets are queued in the PRI_NORMAL modem
895   * output queue.... dump 'em to the priority queue so that they arrive
896   * at the peer before our ResetAck.
897   */
898  link_SequenceQueue(fp->link);
899  fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0);
900  mbuf_Free(bp);
901}
902
903static void
904FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
905{
906  (*fp->fn->RecvResetAck)(fp, lhp->id);
907  mbuf_Free(bp);
908}
909
910void
911fsm_Input(struct fsm *fp, struct mbuf *bp)
912{
913  int len;
914  struct fsmheader *lhp;
915  const struct fsmcodedesc *codep;
916
917  len = mbuf_Length(bp);
918  if (len < sizeof(struct fsmheader)) {
919    mbuf_Free(bp);
920    return;
921  }
922  lhp = (struct fsmheader *) MBUF_CTOP(bp);
923  if (lhp->code < fp->min_code || lhp->code > fp->max_code ||
924      lhp->code > sizeof FsmCodes / sizeof *FsmCodes) {
925    /*
926     * Use a private id.  This is really a response-type packet, but we
927     * MUST send a unique id for each REQ....
928     */
929    static u_char id;
930
931    fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt);
932    mbuf_Free(bp);
933    return;
934  }
935  bp->offset += sizeof(struct fsmheader);
936  bp->cnt -= sizeof(struct fsmheader);
937
938  codep = FsmCodes + lhp->code - 1;
939  if (lhp->id != fp->reqid && codep->check_reqid &&
940      Enabled(fp->bundle, OPT_IDCHECK)) {
941    log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n",
942	      fp->link->name, codep->name, lhp->id, fp->reqid);
943    return;
944  }
945
946  log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n",
947	    fp->link->name, codep->name, lhp->id, State2Nam(fp->state));
948
949  if (log_IsKept(LogDEBUG))
950    mbuf_Log();
951
952  if (codep->inc_reqid && (lhp->id == fp->reqid ||
953      (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid)))
954    fp->reqid++;	/* That's the end of that ``exchange''.... */
955
956  (*codep->recv)(fp, lhp, bp);
957
958  if (log_IsKept(LogDEBUG))
959    mbuf_Log();
960}
961
962void
963fsm_NullRecvResetReq(struct fsm *fp)
964{
965  log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n",
966            fp->link->name);
967}
968
969void
970fsm_NullRecvResetAck(struct fsm *fp, u_char id)
971{
972  log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n",
973            fp->link->name);
974}
975
976void
977fsm_Reopen(struct fsm *fp)
978{
979  if (fp->state == ST_OPENED) {
980    (*fp->fn->LayerDown)(fp);
981    FsmInitRestartCounter(fp);
982    FsmSendConfigReq(fp);
983    NewState(fp, ST_REQSENT);
984    (*fp->parent->LayerDown)(fp->parent->object, fp);
985  }
986}
987
988void
989fsm2initial(struct fsm *fp)
990{
991  if (fp->state == ST_STOPPED)
992    fsm_Close(fp);
993  if (fp->state > ST_INITIAL)
994    fsm_Down(fp);
995  if (fp->state > ST_INITIAL)
996    fsm_Close(fp);
997}
998