fsm.c revision 47169
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.43 1999/05/09 20:02:18 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  /* Check and process easy case */
465  switch (fp->state) {
466  case ST_INITIAL:
467    if (fp->proto == PROTO_CCP && fp->link->lcp.fsm.state == ST_OPENED) {
468      /*
469       * ccp_SetOpenMode() leaves us in initial if we're disabling
470       * & denying everything.
471       */
472      bp = mbuf_Prepend(bp, lhp, sizeof *lhp, 2);
473      bp = proto_Prepend(bp, fp->proto, 0, 0);
474      bp = mbuf_Contiguous(bp);
475      lcp_SendProtoRej(&fp->link->lcp, MBUF_CTOP(bp), bp->cnt);
476      mbuf_Free(bp);
477      return;
478    }
479    /* Drop through */
480  case ST_STARTING:
481    log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n",
482              fp->link->name, State2Nam(fp->state));
483    mbuf_Free(bp);
484    return;
485  case ST_CLOSED:
486    (*fp->fn->SendTerminateAck)(fp, lhp->id);
487    mbuf_Free(bp);
488    return;
489  case ST_CLOSING:
490    log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n",
491              fp->link->name, State2Nam(fp->state));
492  case ST_STOPPING:
493    mbuf_Free(bp);
494    return;
495  case ST_OPENED:
496    (*fp->fn->LayerDown)(fp);
497    (*fp->parent->LayerDown)(fp->parent->object, fp);
498    break;
499  }
500
501  bp = mbuf_Contiguous(bp);
502  dec.ackend = dec.ack;
503  dec.nakend = dec.nak;
504  dec.rejend = dec.rej;
505  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec);
506  if (flen < sizeof(struct fsmconfig))
507    log_Printf(fp->LogLevel, "  [EMPTY]\n");
508
509  if (dec.nakend == dec.nak && dec.rejend == dec.rej)
510    ackaction = 1;
511
512  switch (fp->state) {
513  case ST_STOPPED:
514    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
515    /* Fall through */
516
517  case ST_OPENED:
518    FsmSendConfigReq(fp);
519    break;
520  }
521
522  if (dec.rejend != dec.rej)
523    fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej);
524  if (dec.nakend != dec.nak)
525    fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak);
526  if (ackaction)
527    fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack);
528
529  switch (fp->state) {
530  case ST_STOPPED:
531      /*
532       * According to the RFC (1661) state transition table, a TLS isn't
533       * required for a RCR when state == ST_STOPPED, but the RFC
534       * must be wrong as TLS hasn't yet been called (since the last TLF)
535       */
536    (*fp->fn->LayerStart)(fp);
537    (*fp->parent->LayerStart)(fp->parent->object, fp);
538    /* Fall through */
539
540  case ST_OPENED:
541    if (ackaction)
542      NewState(fp, ST_ACKSENT);
543    else
544      NewState(fp, ST_REQSENT);
545    break;
546  case ST_REQSENT:
547    if (ackaction)
548      NewState(fp, ST_ACKSENT);
549    break;
550  case ST_ACKRCVD:
551    if (ackaction) {
552      NewState(fp, ST_OPENED);
553      if ((*fp->fn->LayerUp)(fp))
554        (*fp->parent->LayerUp)(fp->parent->object, fp);
555      else {
556        (*fp->fn->LayerDown)(fp);
557        FsmInitRestartCounter(fp, FSM_TRM_TIMER);
558        FsmSendTerminateReq(fp);
559        NewState(fp, ST_CLOSING);
560      }
561    }
562    break;
563  case ST_ACKSENT:
564    if (!ackaction)
565      NewState(fp, ST_REQSENT);
566    break;
567  }
568  mbuf_Free(bp);
569
570  if (dec.rejend != dec.rej && --fp->more.rejs <= 0) {
571    log_Printf(LogPHASE, "%s: Too many %s REJs sent - abandoning negotiation\n",
572               fp->link->name, fp->name);
573    fsm_Close(fp);
574  }
575
576  if (dec.nakend != dec.nak && --fp->more.naks <= 0) {
577    log_Printf(LogPHASE, "%s: Too many %s NAKs sent - abandoning negotiation\n",
578               fp->link->name, fp->name);
579    fsm_Close(fp);
580  }
581}
582
583static void
584FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
585/* RCA */
586{
587  switch (fp->state) {
588    case ST_CLOSED:
589    case ST_STOPPED:
590    (*fp->fn->SendTerminateAck)(fp, lhp->id);
591    break;
592  case ST_CLOSING:
593  case ST_STOPPING:
594    break;
595  case ST_REQSENT:
596    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
597    NewState(fp, ST_ACKRCVD);
598    break;
599  case ST_ACKRCVD:
600    FsmSendConfigReq(fp);
601    NewState(fp, ST_REQSENT);
602    break;
603  case ST_ACKSENT:
604    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
605    NewState(fp, ST_OPENED);
606    if ((*fp->fn->LayerUp)(fp))
607      (*fp->parent->LayerUp)(fp->parent->object, fp);
608    else {
609      (*fp->fn->LayerDown)(fp);
610      FsmInitRestartCounter(fp, FSM_TRM_TIMER);
611      FsmSendTerminateReq(fp);
612      NewState(fp, ST_CLOSING);
613    }
614    break;
615  case ST_OPENED:
616    (*fp->fn->LayerDown)(fp);
617    FsmSendConfigReq(fp);
618    NewState(fp, ST_REQSENT);
619    (*fp->parent->LayerDown)(fp->parent->object, fp);
620    break;
621  }
622  mbuf_Free(bp);
623}
624
625static void
626FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
627/* RCN */
628{
629  struct fsm_decode dec;
630  int plen, flen;
631
632  plen = mbuf_Length(bp);
633  flen = ntohs(lhp->length) - sizeof *lhp;
634  if (plen < flen) {
635    mbuf_Free(bp);
636    return;
637  }
638
639  /*
640   * Check and process easy case
641   */
642  switch (fp->state) {
643  case ST_INITIAL:
644  case ST_STARTING:
645    log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n",
646              fp->link->name, State2Nam(fp->state));
647    mbuf_Free(bp);
648    return;
649  case ST_CLOSED:
650  case ST_STOPPED:
651    (*fp->fn->SendTerminateAck)(fp, lhp->id);
652    mbuf_Free(bp);
653    return;
654  case ST_CLOSING:
655  case ST_STOPPING:
656    mbuf_Free(bp);
657    return;
658  }
659
660  bp = mbuf_Contiguous(bp);
661  dec.ackend = dec.ack;
662  dec.nakend = dec.nak;
663  dec.rejend = dec.rej;
664  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec);
665  if (flen < sizeof(struct fsmconfig))
666    log_Printf(fp->LogLevel, "  [EMPTY]\n");
667
668  switch (fp->state) {
669  case ST_REQSENT:
670  case ST_ACKSENT:
671    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
672    FsmSendConfigReq(fp);
673    break;
674  case ST_OPENED:
675    (*fp->fn->LayerDown)(fp);
676    FsmSendConfigReq(fp);
677    NewState(fp, ST_REQSENT);
678    (*fp->parent->LayerDown)(fp->parent->object, fp);
679    break;
680  case ST_ACKRCVD:
681    FsmSendConfigReq(fp);
682    NewState(fp, ST_REQSENT);
683    break;
684  }
685
686  mbuf_Free(bp);
687}
688
689static void
690FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
691/* RTR */
692{
693  switch (fp->state) {
694  case ST_INITIAL:
695  case ST_STARTING:
696    log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n",
697              fp->link->name, State2Nam(fp->state));
698    break;
699  case ST_CLOSED:
700  case ST_STOPPED:
701  case ST_CLOSING:
702  case ST_STOPPING:
703  case ST_REQSENT:
704    (*fp->fn->SendTerminateAck)(fp, lhp->id);
705    break;
706  case ST_ACKRCVD:
707  case ST_ACKSENT:
708    (*fp->fn->SendTerminateAck)(fp, lhp->id);
709    NewState(fp, ST_REQSENT);
710    break;
711  case ST_OPENED:
712    (*fp->fn->LayerDown)(fp);
713    (*fp->fn->SendTerminateAck)(fp, lhp->id);
714    FsmInitRestartCounter(fp, FSM_TRM_TIMER);
715    timer_Start(&fp->FsmTimer);			/* Start restart timer */
716    fp->restart = 0;
717    NewState(fp, ST_STOPPING);
718    (*fp->parent->LayerDown)(fp->parent->object, fp);
719    /* A delayed ST_STOPPED is now scheduled */
720    break;
721  }
722  mbuf_Free(bp);
723}
724
725static void
726FsmRecvTermAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
727/* RTA */
728{
729  switch (fp->state) {
730  case ST_CLOSING:
731    (*fp->fn->LayerFinish)(fp);
732    NewState(fp, ST_CLOSED);
733    (*fp->parent->LayerFinish)(fp->parent->object, fp);
734    break;
735  case ST_STOPPING:
736    (*fp->fn->LayerFinish)(fp);
737    NewState(fp, ST_STOPPED);
738    (*fp->parent->LayerFinish)(fp->parent->object, fp);
739    break;
740  case ST_ACKRCVD:
741    NewState(fp, ST_REQSENT);
742    break;
743  case ST_OPENED:
744    (*fp->fn->LayerDown)(fp);
745    FsmSendConfigReq(fp);
746    NewState(fp, ST_REQSENT);
747    (*fp->parent->LayerDown)(fp->parent->object, fp);
748    break;
749  }
750  mbuf_Free(bp);
751}
752
753static void
754FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
755/* RCJ */
756{
757  struct fsm_decode dec;
758  int plen, flen;
759
760  plen = mbuf_Length(bp);
761  flen = ntohs(lhp->length) - sizeof *lhp;
762  if (plen < flen) {
763    mbuf_Free(bp);
764    return;
765  }
766
767  /*
768   * Check and process easy case
769   */
770  switch (fp->state) {
771  case ST_INITIAL:
772  case ST_STARTING:
773    log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n",
774              fp->link->name, State2Nam(fp->state));
775    mbuf_Free(bp);
776    return;
777  case ST_CLOSED:
778  case ST_STOPPED:
779    (*fp->fn->SendTerminateAck)(fp, lhp->id);
780    mbuf_Free(bp);
781    return;
782  case ST_CLOSING:
783  case ST_STOPPING:
784    mbuf_Free(bp);
785    return;
786  }
787
788  bp = mbuf_Contiguous(bp);
789  dec.ackend = dec.ack;
790  dec.nakend = dec.nak;
791  dec.rejend = dec.rej;
792  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec);
793  if (flen < sizeof(struct fsmconfig))
794    log_Printf(fp->LogLevel, "  [EMPTY]\n");
795
796  switch (fp->state) {
797  case ST_REQSENT:
798  case ST_ACKSENT:
799    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
800    FsmSendConfigReq(fp);
801    break;
802  case ST_OPENED:
803    (*fp->fn->LayerDown)(fp);
804    FsmSendConfigReq(fp);
805    NewState(fp, ST_REQSENT);
806    (*fp->parent->LayerDown)(fp->parent->object, fp);
807    break;
808  case ST_ACKRCVD:
809    FsmSendConfigReq(fp);
810    NewState(fp, ST_REQSENT);
811    break;
812  }
813  mbuf_Free(bp);
814}
815
816static void
817FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
818{
819  mbuf_Free(bp);
820}
821
822static void
823FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
824{
825  struct physical *p = link2physical(fp->link);
826  u_short proto;
827
828  if (mbuf_Length(bp) < 2) {
829    mbuf_Free(bp);
830    return;
831  }
832  bp = mbuf_Read(bp, &proto, 2);
833  proto = ntohs(proto);
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 && mbuf_Length(bp) >= 4) {
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  if (fsm2lcp(fp))
904    bp = lqr_RecvEcho(fp, bp);
905
906  mbuf_Free(bp);
907}
908
909static void
910FsmRecvDiscReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
911{
912  mbuf_Free(bp);
913}
914
915static void
916FsmRecvIdent(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
917{
918  mbuf_Free(bp);
919}
920
921static void
922FsmRecvTimeRemain(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
923{
924  mbuf_Free(bp);
925}
926
927static void
928FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
929{
930  (*fp->fn->RecvResetReq)(fp);
931  /*
932   * All sendable compressed packets are queued in the PRI_NORMAL modem
933   * output queue.... dump 'em to the priority queue so that they arrive
934   * at the peer before our ResetAck.
935   */
936  link_SequenceQueue(fp->link);
937  fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0);
938  mbuf_Free(bp);
939}
940
941static void
942FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
943{
944  (*fp->fn->RecvResetAck)(fp, lhp->id);
945  mbuf_Free(bp);
946}
947
948void
949fsm_Input(struct fsm *fp, struct mbuf *bp)
950{
951  int len;
952  struct fsmheader lh;
953  const struct fsmcodedesc *codep;
954
955  len = mbuf_Length(bp);
956  if (len < sizeof(struct fsmheader)) {
957    mbuf_Free(bp);
958    return;
959  }
960  bp = mbuf_Read(bp, &lh, sizeof lh);
961  if (lh.code < fp->min_code || lh.code > fp->max_code ||
962      lh.code > sizeof FsmCodes / sizeof *FsmCodes) {
963    /*
964     * Use a private id.  This is really a response-type packet, but we
965     * MUST send a unique id for each REQ....
966     */
967    static u_char id;
968
969    bp = mbuf_Prepend(bp, &lh, sizeof lh, 0);
970    bp = mbuf_Contiguous(bp);
971    fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt);
972    mbuf_Free(bp);
973    return;
974  }
975
976  codep = FsmCodes + lh.code - 1;
977  if (lh.id != fp->reqid && codep->check_reqid &&
978      Enabled(fp->bundle, OPT_IDCHECK)) {
979    log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n",
980	      fp->link->name, codep->name, lh.id, fp->reqid);
981    return;
982  }
983
984  log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n",
985	    fp->link->name, codep->name, lh.id, State2Nam(fp->state));
986
987  if (log_IsKept(LogDEBUG))
988    mbuf_Log();
989
990  if (codep->inc_reqid && (lh.id == fp->reqid ||
991      (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid)))
992    fp->reqid++;	/* That's the end of that ``exchange''.... */
993
994  (*codep->recv)(fp, &lh, bp);
995
996  if (log_IsKept(LogDEBUG))
997    mbuf_Log();
998}
999
1000void
1001fsm_NullRecvResetReq(struct fsm *fp)
1002{
1003  log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n",
1004            fp->link->name);
1005}
1006
1007void
1008fsm_NullRecvResetAck(struct fsm *fp, u_char id)
1009{
1010  log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n",
1011            fp->link->name);
1012}
1013
1014void
1015fsm_Reopen(struct fsm *fp)
1016{
1017  if (fp->state == ST_OPENED) {
1018    (*fp->fn->LayerDown)(fp);
1019    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
1020    FsmSendConfigReq(fp);
1021    NewState(fp, ST_REQSENT);
1022    (*fp->parent->LayerDown)(fp->parent->object, fp);
1023  }
1024}
1025
1026void
1027fsm2initial(struct fsm *fp)
1028{
1029  timer_Stop(&fp->FsmTimer);
1030  timer_Stop(&fp->OpenTimer);
1031  timer_Stop(&fp->StoppedTimer);
1032  if (fp->state == ST_STOPPED)
1033    fsm_Close(fp);
1034  if (fp->state > ST_INITIAL)
1035    fsm_Down(fp);
1036  if (fp->state > ST_INITIAL)
1037    fsm_Close(fp);
1038}
1039