fsm.c revision 46686
1/*
2 *		PPP Finite State Machine for LCP/IPCP
3 *
4 *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc.  The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: fsm.c,v 1.41 1999/03/29 08:21:26 brian Exp $
21 *
22 *  TODO:
23 */
24
25#include <sys/param.h>
26#include <netinet/in.h>
27#include <netinet/in_systm.h>
28#include <netinet/ip.h>
29#include <sys/un.h>
30
31#include <string.h>
32#include <termios.h>
33
34#include "layer.h"
35#include "ua.h"
36#include "mbuf.h"
37#include "log.h"
38#include "defs.h"
39#include "timer.h"
40#include "fsm.h"
41#include "iplist.h"
42#include "lqr.h"
43#include "hdlc.h"
44#include "throughput.h"
45#include "slcompress.h"
46#include "ipcp.h"
47#include "filter.h"
48#include "descriptor.h"
49#include "lcp.h"
50#include "ccp.h"
51#include "link.h"
52#include "mp.h"
53#ifndef NORADIUS
54#include "radius.h"
55#endif
56#include "bundle.h"
57#include "async.h"
58#include "physical.h"
59#include "proto.h"
60
61static void FsmSendConfigReq(struct fsm *);
62static void FsmSendTerminateReq(struct fsm *);
63static void FsmInitRestartCounter(struct fsm *, int);
64
65typedef void (recvfn)(struct fsm *, struct fsmheader *, struct mbuf *);
66static recvfn FsmRecvConfigReq, FsmRecvConfigAck, FsmRecvConfigNak,
67              FsmRecvConfigRej, FsmRecvTermReq, FsmRecvTermAck,
68              FsmRecvCodeRej, FsmRecvProtoRej, FsmRecvEchoReq,
69              FsmRecvEchoRep, FsmRecvDiscReq, FsmRecvIdent,
70              FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck;
71
72static const struct fsmcodedesc {
73  recvfn *recv;
74  unsigned check_reqid : 1;
75  unsigned inc_reqid : 1;
76  const char *name;
77} FsmCodes[] = {
78  { FsmRecvConfigReq, 0, 0, "ConfigReq"    },
79  { FsmRecvConfigAck, 1, 1, "ConfigAck"    },
80  { FsmRecvConfigNak, 1, 1, "ConfigNak"    },
81  { FsmRecvConfigRej, 1, 1, "ConfigRej"    },
82  { FsmRecvTermReq,   0, 0, "TerminateReq" },
83  { FsmRecvTermAck,   1, 1, "TerminateAck" },
84  { FsmRecvCodeRej,   0, 0, "CodeRej"      },
85  { FsmRecvProtoRej,  0, 0, "ProtocolRej"  },
86  { FsmRecvEchoReq,   0, 0, "EchoRequest"  },
87  { FsmRecvEchoRep,   0, 0, "EchoReply"    },
88  { FsmRecvDiscReq,   0, 0, "DiscardReq"   },
89  { FsmRecvIdent,     0, 0, "Ident"        },
90  { FsmRecvTimeRemain,0, 0, "TimeRemain"   },
91  { FsmRecvResetReq,  0, 0, "ResetReq"     },
92  { FsmRecvResetAck,  0, 1, "ResetAck"     }
93};
94
95static const char *
96Code2Nam(u_int code)
97{
98  if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0])
99    return "Unknown";
100  return FsmCodes[code-1].name;
101}
102
103const char *
104State2Nam(u_int state)
105{
106  static const char *StateNames[] = {
107    "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
108    "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
109  };
110
111  if (state >= sizeof StateNames / sizeof StateNames[0])
112    return "unknown";
113  return StateNames[state];
114}
115
116static void
117StoppedTimeout(void *v)
118{
119  struct fsm *fp = (struct fsm *)v;
120
121  log_Printf(fp->LogLevel, "%s: Stopped timer expired\n", fp->link->name);
122  if (fp->OpenTimer.state == TIMER_RUNNING) {
123    log_Printf(LogWARN, "%s: %s: aborting open delay due to stopped timer\n",
124              fp->link->name, fp->name);
125    timer_Stop(&fp->OpenTimer);
126  }
127  if (fp->state == ST_STOPPED)
128    fsm2initial(fp);
129}
130
131void
132fsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode,
133         int maxcode, int LogLevel, struct bundle *bundle,
134         struct link *l, const struct fsm_parent *parent,
135         struct fsm_callbacks *fn, const char *timer_names[3])
136{
137  fp->name = name;
138  fp->proto = proto;
139  fp->min_code = mincode;
140  fp->max_code = maxcode;
141  fp->state = fp->min_code > CODE_TERMACK ? ST_OPENED : ST_INITIAL;
142  fp->reqid = 1;
143  fp->restart = 1;
144  fp->more.reqs = fp->more.naks = fp->more.rejs = 3;
145  memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer);
146  memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer);
147  memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer);
148  fp->LogLevel = LogLevel;
149  fp->link = l;
150  fp->bundle = bundle;
151  fp->parent = parent;
152  fp->fn = fn;
153  fp->FsmTimer.name = timer_names[0];
154  fp->OpenTimer.name = timer_names[1];
155  fp->StoppedTimer.name = timer_names[2];
156}
157
158static void
159NewState(struct fsm * fp, int new)
160{
161  log_Printf(fp->LogLevel, "%s: State change %s --> %s\n",
162	    fp->link->name, State2Nam(fp->state), State2Nam(new));
163  if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
164    timer_Stop(&fp->StoppedTimer);
165  fp->state = new;
166  if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
167    timer_Stop(&fp->FsmTimer);
168    if (new == ST_STOPPED && fp->StoppedTimer.load) {
169      timer_Stop(&fp->StoppedTimer);
170      fp->StoppedTimer.func = StoppedTimeout;
171      fp->StoppedTimer.arg = (void *) fp;
172      timer_Start(&fp->StoppedTimer);
173    }
174  }
175}
176
177void
178fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count)
179{
180  int plen;
181  struct fsmheader lh;
182  struct mbuf *bp;
183
184  if (log_IsKept(fp->LogLevel)) {
185    log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n",
186              fp->link->name, Code2Nam(code), id, State2Nam(fp->state));
187    switch (code) {
188      case CODE_CONFIGREQ:
189      case CODE_CONFIGACK:
190      case CODE_CONFIGREJ:
191      case CODE_CONFIGNAK:
192        (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL);
193        if (count < sizeof(struct fsmconfig))
194          log_Printf(fp->LogLevel, "  [EMPTY]\n");
195        break;
196    }
197  }
198
199  plen = sizeof(struct fsmheader) + count;
200  lh.code = code;
201  lh.id = id;
202  lh.length = htons(plen);
203  bp = mbuf_Alloc(plen, MB_FSM);
204  memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
205  if (count)
206    memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
207  log_DumpBp(LogDEBUG, "fsm_Output", bp);
208  link_PushPacket(fp->link, bp, fp->bundle, PRI_LINK, fp->proto);
209}
210
211static void
212FsmOpenNow(void *v)
213{
214  struct fsm *fp = (struct fsm *)v;
215
216  timer_Stop(&fp->OpenTimer);
217  if (fp->state <= ST_STOPPED) {
218    if (fp->state != ST_STARTING) {
219      /*
220       * In practice, we're only here in ST_STOPPED (when delaying the
221       * first config request) or ST_CLOSED (when openmode == 0).
222       *
223       * The ST_STOPPED bit is breaking the RFC already :-(
224       *
225       * According to the RFC (1661) state transition table, a TLS isn't
226       * required for an Open event when state == Closed, but the RFC
227       * must be wrong as TLS hasn't yet been called (since the last TLF)
228       * ie, Initial gets an `Up' event, Closing gets a RTA etc.
229       */
230      (*fp->fn->LayerStart)(fp);
231      (*fp->parent->LayerStart)(fp->parent->object, fp);
232    }
233    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
234    FsmSendConfigReq(fp);
235    NewState(fp, ST_REQSENT);
236  }
237}
238
239void
240fsm_Open(struct fsm * fp)
241{
242  switch (fp->state) {
243  case ST_INITIAL:
244    NewState(fp, ST_STARTING);
245    (*fp->fn->LayerStart)(fp);
246    (*fp->parent->LayerStart)(fp->parent->object, fp);
247    break;
248  case ST_CLOSED:
249    if (fp->open_mode == OPEN_PASSIVE) {
250      NewState(fp, ST_STOPPED);		/* XXX: This is a hack ! */
251    } else if (fp->open_mode > 0) {
252      if (fp->open_mode > 1)
253        log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n",
254                  fp->link->name, fp->open_mode);
255      NewState(fp, ST_STOPPED);		/* XXX: This is a not-so-bad hack ! */
256      timer_Stop(&fp->OpenTimer);
257      fp->OpenTimer.load = fp->open_mode * SECTICKS;
258      fp->OpenTimer.func = FsmOpenNow;
259      fp->OpenTimer.arg = (void *)fp;
260      timer_Start(&fp->OpenTimer);
261    } else
262      FsmOpenNow(fp);
263    break;
264  case ST_STOPPED:		/* XXX: restart option */
265  case ST_REQSENT:
266  case ST_ACKRCVD:
267  case ST_ACKSENT:
268  case ST_OPENED:		/* XXX: restart option */
269    break;
270  case ST_CLOSING:		/* XXX: restart option */
271  case ST_STOPPING:		/* XXX: restart option */
272    NewState(fp, ST_STOPPING);
273    break;
274  }
275}
276
277void
278fsm_Up(struct fsm * fp)
279{
280  switch (fp->state) {
281  case ST_INITIAL:
282    log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n",
283              fp->link->name);
284    NewState(fp, ST_CLOSED);
285    break;
286  case ST_STARTING:
287    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
288    FsmSendConfigReq(fp);
289    NewState(fp, ST_REQSENT);
290    break;
291  default:
292    log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n",
293              fp->link->name, State2Nam(fp->state));
294    break;
295  }
296}
297
298void
299fsm_Down(struct fsm *fp)
300{
301  switch (fp->state) {
302  case ST_CLOSED:
303    NewState(fp, ST_INITIAL);
304    break;
305  case ST_CLOSING:
306    /* This TLF contradicts the RFC (1661), which ``misses it out'' ! */
307    (*fp->fn->LayerFinish)(fp);
308    NewState(fp, ST_INITIAL);
309    (*fp->parent->LayerFinish)(fp->parent->object, fp);
310    break;
311  case ST_STOPPED:
312    NewState(fp, ST_STARTING);
313    (*fp->fn->LayerStart)(fp);
314    (*fp->parent->LayerStart)(fp->parent->object, fp);
315    break;
316  case ST_STOPPING:
317  case ST_REQSENT:
318  case ST_ACKRCVD:
319  case ST_ACKSENT:
320    NewState(fp, ST_STARTING);
321    break;
322  case ST_OPENED:
323    (*fp->fn->LayerDown)(fp);
324    NewState(fp, ST_STARTING);
325    (*fp->parent->LayerDown)(fp->parent->object, fp);
326    break;
327  }
328}
329
330void
331fsm_Close(struct fsm *fp)
332{
333  switch (fp->state) {
334  case ST_STARTING:
335    (*fp->fn->LayerFinish)(fp);
336    NewState(fp, ST_INITIAL);
337    (*fp->parent->LayerFinish)(fp->parent->object, fp);
338    break;
339  case ST_STOPPED:
340    NewState(fp, ST_CLOSED);
341    break;
342  case ST_STOPPING:
343    NewState(fp, ST_CLOSING);
344    break;
345  case ST_OPENED:
346    (*fp->fn->LayerDown)(fp);
347    FsmInitRestartCounter(fp, FSM_TRM_TIMER);
348    FsmSendTerminateReq(fp);
349    NewState(fp, ST_CLOSING);
350    (*fp->parent->LayerDown)(fp->parent->object, fp);
351    break;
352  case ST_REQSENT:
353  case ST_ACKRCVD:
354  case ST_ACKSENT:
355    FsmInitRestartCounter(fp, FSM_TRM_TIMER);
356    FsmSendTerminateReq(fp);
357    NewState(fp, ST_CLOSING);
358    break;
359  }
360}
361
362/*
363 *	Send functions
364 */
365static void
366FsmSendConfigReq(struct fsm * fp)
367{
368  if (fp->more.reqs-- > 0 && fp->restart-- > 0) {
369    (*fp->fn->SendConfigReq)(fp);
370    timer_Start(&fp->FsmTimer);		/* Start restart timer */
371  } else {
372    if (fp->more.reqs < 0)
373      log_Printf(LogPHASE, "%s: Too many %s REQs sent - abandoning "
374                 "negotiation\n", fp->link->name, fp->name);
375    fsm_Close(fp);
376  }
377}
378
379static void
380FsmSendTerminateReq(struct fsm *fp)
381{
382  fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0);
383  (*fp->fn->SentTerminateReq)(fp);
384  timer_Start(&fp->FsmTimer);	/* Start restart timer */
385  fp->restart--;		/* Decrement restart counter */
386}
387
388/*
389 *	Timeout actions
390 */
391static void
392FsmTimeout(void *v)
393{
394  struct fsm *fp = (struct fsm *)v;
395
396  if (fp->restart) {
397    switch (fp->state) {
398    case ST_CLOSING:
399    case ST_STOPPING:
400      FsmSendTerminateReq(fp);
401      break;
402    case ST_REQSENT:
403    case ST_ACKSENT:
404      FsmSendConfigReq(fp);
405      break;
406    case ST_ACKRCVD:
407      FsmSendConfigReq(fp);
408      NewState(fp, ST_REQSENT);
409      break;
410    }
411    timer_Start(&fp->FsmTimer);
412  } else {
413    switch (fp->state) {
414    case ST_CLOSING:
415      (*fp->fn->LayerFinish)(fp);
416      NewState(fp, ST_CLOSED);
417      (*fp->parent->LayerFinish)(fp->parent->object, fp);
418      break;
419    case ST_STOPPING:
420      (*fp->fn->LayerFinish)(fp);
421      NewState(fp, ST_STOPPED);
422      (*fp->parent->LayerFinish)(fp->parent->object, fp);
423      break;
424    case ST_REQSENT:		/* XXX: 3p */
425    case ST_ACKSENT:
426    case ST_ACKRCVD:
427      (*fp->fn->LayerFinish)(fp);
428      NewState(fp, ST_STOPPED);
429      (*fp->parent->LayerFinish)(fp->parent->object, fp);
430      break;
431    }
432  }
433}
434
435static void
436FsmInitRestartCounter(struct fsm *fp, int what)
437{
438  timer_Stop(&fp->FsmTimer);
439  fp->FsmTimer.func = FsmTimeout;
440  fp->FsmTimer.arg = (void *)fp;
441  (*fp->fn->InitRestartCounter)(fp, what);
442}
443
444/*
445 *   Actions when receive packets
446 */
447static void
448FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
449/* RCR */
450{
451  struct fsm_decode dec;
452  int plen, flen;
453  int ackaction = 0;
454
455  plen = mbuf_Length(bp);
456  flen = ntohs(lhp->length) - sizeof *lhp;
457  if (plen < flen) {
458    log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",
459	      fp->link->name, plen, flen);
460    mbuf_Free(bp);
461    return;
462  }
463
464  /*
465   * Check and process easy case
466   */
467  switch (fp->state) {
468  case ST_INITIAL:
469    if (fp->proto == PROTO_CCP && fp->link->lcp.fsm.state == ST_OPENED) {
470      /*
471       * ccp_SetOpenMode() leaves us in initial if we're disabling
472       * & denying everything.
473       *
474       * this is a bit smelly... we know that bp has a leading fsmheader.
475       */
476      bp = mbuf_Prepend(bp, lhp, sizeof *lhp, 2);
477      bp = proto_Prepend(bp, fp->proto, 0, 0);
478      bp = mbuf_Contiguous(bp);
479      lcp_SendProtoRej(&fp->link->lcp, MBUF_CTOP(bp), bp->cnt);
480      mbuf_Free(bp);
481      return;
482    }
483    /* Drop through */
484  case ST_STARTING:
485    log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n",
486              fp->link->name, State2Nam(fp->state));
487    mbuf_Free(bp);
488    return;
489  case ST_CLOSED:
490    (*fp->fn->SendTerminateAck)(fp, lhp->id);
491    mbuf_Free(bp);
492    return;
493  case ST_CLOSING:
494    log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n",
495              fp->link->name, State2Nam(fp->state));
496  case ST_STOPPING:
497    mbuf_Free(bp);
498    return;
499  case ST_OPENED:
500    (*fp->fn->LayerDown)(fp);
501    (*fp->parent->LayerDown)(fp->parent->object, fp);
502    break;
503  }
504
505  bp = mbuf_Contiguous(bp);
506
507  dec.ackend = dec.ack;
508  dec.nakend = dec.nak;
509  dec.rejend = dec.rej;
510  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec);
511  if (flen < sizeof(struct fsmconfig))
512    log_Printf(fp->LogLevel, "  [EMPTY]\n");
513
514  if (dec.nakend == dec.nak && dec.rejend == dec.rej)
515    ackaction = 1;
516
517  switch (fp->state) {
518  case ST_STOPPED:
519    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
520    /* Fall through */
521
522  case ST_OPENED:
523    FsmSendConfigReq(fp);
524    break;
525  }
526
527  if (dec.rejend != dec.rej)
528    fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej);
529  if (dec.nakend != dec.nak)
530    fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak);
531  if (ackaction)
532    fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack);
533
534  switch (fp->state) {
535  case ST_STOPPED:
536      /*
537       * According to the RFC (1661) state transition table, a TLS isn't
538       * required for a RCR when state == ST_STOPPED, but the RFC
539       * must be wrong as TLS hasn't yet been called (since the last TLF)
540       */
541    (*fp->fn->LayerStart)(fp);
542    (*fp->parent->LayerStart)(fp->parent->object, fp);
543    /* Fall through */
544
545  case ST_OPENED:
546    if (ackaction)
547      NewState(fp, ST_ACKSENT);
548    else
549      NewState(fp, ST_REQSENT);
550    break;
551  case ST_REQSENT:
552    if (ackaction)
553      NewState(fp, ST_ACKSENT);
554    break;
555  case ST_ACKRCVD:
556    if (ackaction) {
557      NewState(fp, ST_OPENED);
558      if ((*fp->fn->LayerUp)(fp))
559        (*fp->parent->LayerUp)(fp->parent->object, fp);
560      else {
561        (*fp->fn->LayerDown)(fp);
562        FsmInitRestartCounter(fp, FSM_TRM_TIMER);
563        FsmSendTerminateReq(fp);
564        NewState(fp, ST_CLOSING);
565      }
566    }
567    break;
568  case ST_ACKSENT:
569    if (!ackaction)
570      NewState(fp, ST_REQSENT);
571    break;
572  }
573  mbuf_Free(bp);
574
575  if (dec.rejend != dec.rej && --fp->more.rejs <= 0) {
576    log_Printf(LogPHASE, "%s: Too many %s REJs sent - abandoning negotiation\n",
577               fp->link->name, fp->name);
578    fsm_Close(fp);
579  }
580
581  if (dec.nakend != dec.nak && --fp->more.naks <= 0) {
582    log_Printf(LogPHASE, "%s: Too many %s NAKs sent - abandoning negotiation\n",
583               fp->link->name, fp->name);
584    fsm_Close(fp);
585  }
586}
587
588static void
589FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
590/* RCA */
591{
592  switch (fp->state) {
593    case ST_CLOSED:
594    case ST_STOPPED:
595    (*fp->fn->SendTerminateAck)(fp, lhp->id);
596    break;
597  case ST_CLOSING:
598  case ST_STOPPING:
599    break;
600  case ST_REQSENT:
601    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
602    NewState(fp, ST_ACKRCVD);
603    break;
604  case ST_ACKRCVD:
605    FsmSendConfigReq(fp);
606    NewState(fp, ST_REQSENT);
607    break;
608  case ST_ACKSENT:
609    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
610    NewState(fp, ST_OPENED);
611    if ((*fp->fn->LayerUp)(fp))
612      (*fp->parent->LayerUp)(fp->parent->object, fp);
613    else {
614      (*fp->fn->LayerDown)(fp);
615      FsmInitRestartCounter(fp, FSM_TRM_TIMER);
616      FsmSendTerminateReq(fp);
617      NewState(fp, ST_CLOSING);
618    }
619    break;
620  case ST_OPENED:
621    (*fp->fn->LayerDown)(fp);
622    FsmSendConfigReq(fp);
623    NewState(fp, ST_REQSENT);
624    (*fp->parent->LayerDown)(fp->parent->object, fp);
625    break;
626  }
627  mbuf_Free(bp);
628}
629
630static void
631FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
632/* RCN */
633{
634  struct fsm_decode dec;
635  int plen, flen;
636
637  plen = mbuf_Length(bp);
638  flen = ntohs(lhp->length) - sizeof *lhp;
639  if (plen < flen) {
640    mbuf_Free(bp);
641    return;
642  }
643
644  /*
645   * Check and process easy case
646   */
647  switch (fp->state) {
648  case ST_INITIAL:
649  case ST_STARTING:
650    log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n",
651              fp->link->name, State2Nam(fp->state));
652    mbuf_Free(bp);
653    return;
654  case ST_CLOSED:
655  case ST_STOPPED:
656    (*fp->fn->SendTerminateAck)(fp, lhp->id);
657    mbuf_Free(bp);
658    return;
659  case ST_CLOSING:
660  case ST_STOPPING:
661    mbuf_Free(bp);
662    return;
663  }
664
665  dec.ackend = dec.ack;
666  dec.nakend = dec.nak;
667  dec.rejend = dec.rej;
668  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec);
669  if (flen < sizeof(struct fsmconfig))
670    log_Printf(fp->LogLevel, "  [EMPTY]\n");
671
672  switch (fp->state) {
673  case ST_REQSENT:
674  case ST_ACKSENT:
675    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
676    FsmSendConfigReq(fp);
677    break;
678  case ST_OPENED:
679    (*fp->fn->LayerDown)(fp);
680    FsmSendConfigReq(fp);
681    NewState(fp, ST_REQSENT);
682    (*fp->parent->LayerDown)(fp->parent->object, fp);
683    break;
684  case ST_ACKRCVD:
685    FsmSendConfigReq(fp);
686    NewState(fp, ST_REQSENT);
687    break;
688  }
689
690  mbuf_Free(bp);
691}
692
693static void
694FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
695/* RTR */
696{
697  switch (fp->state) {
698  case ST_INITIAL:
699  case ST_STARTING:
700    log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n",
701              fp->link->name, State2Nam(fp->state));
702    break;
703  case ST_CLOSED:
704  case ST_STOPPED:
705  case ST_CLOSING:
706  case ST_STOPPING:
707  case ST_REQSENT:
708    (*fp->fn->SendTerminateAck)(fp, lhp->id);
709    break;
710  case ST_ACKRCVD:
711  case ST_ACKSENT:
712    (*fp->fn->SendTerminateAck)(fp, lhp->id);
713    NewState(fp, ST_REQSENT);
714    break;
715  case ST_OPENED:
716    (*fp->fn->LayerDown)(fp);
717    (*fp->fn->SendTerminateAck)(fp, lhp->id);
718    FsmInitRestartCounter(fp, FSM_TRM_TIMER);
719    timer_Start(&fp->FsmTimer);			/* Start restart timer */
720    fp->restart = 0;
721    NewState(fp, ST_STOPPING);
722    (*fp->parent->LayerDown)(fp->parent->object, fp);
723    /* A delayed ST_STOPPED is now scheduled */
724    break;
725  }
726  mbuf_Free(bp);
727}
728
729static void
730FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
731/* RTA */
732{
733  switch (fp->state) {
734  case ST_CLOSING:
735    (*fp->fn->LayerFinish)(fp);
736    NewState(fp, ST_CLOSED);
737    (*fp->parent->LayerFinish)(fp->parent->object, fp);
738    break;
739  case ST_STOPPING:
740    (*fp->fn->LayerFinish)(fp);
741    NewState(fp, ST_STOPPED);
742    (*fp->parent->LayerFinish)(fp->parent->object, fp);
743    break;
744  case ST_ACKRCVD:
745    NewState(fp, ST_REQSENT);
746    break;
747  case ST_OPENED:
748    (*fp->fn->LayerDown)(fp);
749    FsmSendConfigReq(fp);
750    NewState(fp, ST_REQSENT);
751    (*fp->parent->LayerDown)(fp->parent->object, fp);
752    break;
753  }
754  mbuf_Free(bp);
755}
756
757static void
758FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
759/* RCJ */
760{
761  struct fsm_decode dec;
762  int plen, flen;
763
764  plen = mbuf_Length(bp);
765  flen = ntohs(lhp->length) - sizeof *lhp;
766  if (plen < flen) {
767    mbuf_Free(bp);
768    return;
769  }
770
771  /*
772   * Check and process easy case
773   */
774  switch (fp->state) {
775  case ST_INITIAL:
776  case ST_STARTING:
777    log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n",
778              fp->link->name, State2Nam(fp->state));
779    mbuf_Free(bp);
780    return;
781  case ST_CLOSED:
782  case ST_STOPPED:
783    (*fp->fn->SendTerminateAck)(fp, lhp->id);
784    mbuf_Free(bp);
785    return;
786  case ST_CLOSING:
787  case ST_STOPPING:
788    mbuf_Free(bp);
789    return;
790  }
791
792  dec.ackend = dec.ack;
793  dec.nakend = dec.nak;
794  dec.rejend = dec.rej;
795  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec);
796  if (flen < sizeof(struct fsmconfig))
797    log_Printf(fp->LogLevel, "  [EMPTY]\n");
798
799  switch (fp->state) {
800  case ST_REQSENT:
801  case ST_ACKSENT:
802    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
803    FsmSendConfigReq(fp);
804    break;
805  case ST_OPENED:
806    (*fp->fn->LayerDown)(fp);
807    FsmSendConfigReq(fp);
808    NewState(fp, ST_REQSENT);
809    (*fp->parent->LayerDown)(fp->parent->object, fp);
810    break;
811  case ST_ACKRCVD:
812    FsmSendConfigReq(fp);
813    NewState(fp, ST_REQSENT);
814    break;
815  }
816  mbuf_Free(bp);
817}
818
819static void
820FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
821{
822  mbuf_Free(bp);
823}
824
825static void
826FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
827{
828  struct physical *p = link2physical(fp->link);
829  u_short *sp, proto;
830
831  bp = mbuf_Contiguous(bp);
832  sp = (u_short *)MBUF_CTOP(bp);
833  proto = ntohs(*sp);
834  log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n",
835            fp->link->name, proto, hdlc_Protocol2Nam(proto));
836
837  switch (proto) {
838  case PROTO_LQR:
839    if (p)
840      lqr_Stop(p, LQM_LQR);
841    else
842      log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n",
843                fp->link->name);
844    break;
845  case PROTO_CCP:
846    if (fp->proto == PROTO_LCP) {
847      fp = &fp->link->ccp.fsm;
848      /* Despite the RFC (1661), don't do an out-of-place TLF */
849      /* (*fp->fn->LayerFinish)(fp); */
850      switch (fp->state) {
851      case ST_CLOSED:
852      case ST_CLOSING:
853        NewState(fp, ST_CLOSED);
854      default:
855        NewState(fp, ST_STOPPED);
856        break;
857      }
858      /* See above */
859      /* (*fp->parent->LayerFinish)(fp->parent->object, fp); */
860    }
861    break;
862  case PROTO_MP:
863    if (fp->proto == PROTO_LCP) {
864      struct lcp *lcp = fsm2lcp(fp);
865
866      if (lcp->want_mrru && lcp->his_mrru) {
867        log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n",
868                  fp->link->name);
869        fsm_Close(fp);
870      }
871    }
872    break;
873  }
874  mbuf_Free(bp);
875}
876
877static void
878FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
879{
880  struct lcp *lcp = fsm2lcp(fp);
881  u_char *cp;
882  u_int32_t magic;
883
884  if (lcp) {
885    cp = MBUF_CTOP(bp);
886    ua_ntohl(cp, &magic);
887    if (magic != lcp->his_magic) {
888      log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n",
889                fp->link->name);
890      /* XXX: We should send terminate request */
891    }
892    if (fp->state == ST_OPENED) {
893      ua_htonl(&lcp->want_magic, cp);		/* local magic */
894      fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp));
895    }
896  }
897  mbuf_Free(bp);
898}
899
900static void
901FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
902{
903  struct lcp *lcp = fsm2lcp(fp);
904  u_int32_t magic;
905
906  if (lcp) {
907    ua_ntohl(MBUF_CTOP(bp), &magic);
908    /* Tolerate echo replies with either magic number */
909    if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) {
910      log_Printf(LogWARN,
911                "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n",
912	        fp->link->name, lcp->his_magic, magic);
913      /*
914       * XXX: We should send terminate request. But poor implementations may
915       * die as a result.
916       */
917    }
918    lqr_RecvEcho(fp, bp);
919  }
920  mbuf_Free(bp);
921}
922
923static void
924FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
925{
926  mbuf_Free(bp);
927}
928
929static void
930FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
931{
932  mbuf_Free(bp);
933}
934
935static void
936FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
937{
938  mbuf_Free(bp);
939}
940
941static void
942FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
943{
944  (*fp->fn->RecvResetReq)(fp);
945  /*
946   * All sendable compressed packets are queued in the PRI_NORMAL modem
947   * output queue.... dump 'em to the priority queue so that they arrive
948   * at the peer before our ResetAck.
949   */
950  link_SequenceQueue(fp->link);
951  fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0);
952  mbuf_Free(bp);
953}
954
955static void
956FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
957{
958  (*fp->fn->RecvResetAck)(fp, lhp->id);
959  mbuf_Free(bp);
960}
961
962void
963fsm_Input(struct fsm *fp, struct mbuf *bp)
964{
965  int len;
966  struct fsmheader lh;
967  const struct fsmcodedesc *codep;
968
969  len = mbuf_Length(bp);
970  if (len < sizeof(struct fsmheader)) {
971    mbuf_Free(bp);
972    return;
973  }
974  bp = mbuf_Read(bp, &lh, sizeof lh);
975  if (lh.code < fp->min_code || lh.code > fp->max_code ||
976      lh.code > sizeof FsmCodes / sizeof *FsmCodes) {
977    /*
978     * Use a private id.  This is really a response-type packet, but we
979     * MUST send a unique id for each REQ....
980     */
981    static u_char id;
982
983    bp = mbuf_Prepend(bp, &lh, sizeof lh, 0);
984    bp = mbuf_Contiguous(bp);
985    fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt);
986    mbuf_Free(bp);
987    return;
988  }
989
990  codep = FsmCodes + lh.code - 1;
991  if (lh.id != fp->reqid && codep->check_reqid &&
992      Enabled(fp->bundle, OPT_IDCHECK)) {
993    log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n",
994	      fp->link->name, codep->name, lh.id, fp->reqid);
995    return;
996  }
997
998  log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n",
999	    fp->link->name, codep->name, lh.id, State2Nam(fp->state));
1000
1001  if (log_IsKept(LogDEBUG))
1002    mbuf_Log();
1003
1004  if (codep->inc_reqid && (lh.id == fp->reqid ||
1005      (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid)))
1006    fp->reqid++;	/* That's the end of that ``exchange''.... */
1007
1008  (*codep->recv)(fp, &lh, bp);
1009
1010  if (log_IsKept(LogDEBUG))
1011    mbuf_Log();
1012}
1013
1014void
1015fsm_NullRecvResetReq(struct fsm *fp)
1016{
1017  log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n",
1018            fp->link->name);
1019}
1020
1021void
1022fsm_NullRecvResetAck(struct fsm *fp, u_char id)
1023{
1024  log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n",
1025            fp->link->name);
1026}
1027
1028void
1029fsm_Reopen(struct fsm *fp)
1030{
1031  if (fp->state == ST_OPENED) {
1032    (*fp->fn->LayerDown)(fp);
1033    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
1034    FsmSendConfigReq(fp);
1035    NewState(fp, ST_REQSENT);
1036    (*fp->parent->LayerDown)(fp->parent->object, fp);
1037  }
1038}
1039
1040void
1041fsm2initial(struct fsm *fp)
1042{
1043  timer_Stop(&fp->FsmTimer);
1044  timer_Stop(&fp->OpenTimer);
1045  timer_Stop(&fp->StoppedTimer);
1046  if (fp->state == ST_STOPPED)
1047    fsm_Close(fp);
1048  if (fp->state > ST_INITIAL)
1049    fsm_Down(fp);
1050  if (fp->state > ST_INITIAL)
1051    fsm_Close(fp);
1052}
1053