fsm.c revision 71658
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 * $FreeBSD: head/usr.sbin/ppp/fsm.c 71658 2001-01-26 01:43:38Z brian $
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, 1, "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 * const 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 * const 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           int mtype)
180{
181  int plen;
182  struct fsmheader lh;
183  struct mbuf *bp;
184
185  if (log_IsKept(fp->LogLevel)) {
186    log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n",
187              fp->link->name, Code2Nam(code), id, State2Nam(fp->state));
188    switch (code) {
189      case CODE_CONFIGREQ:
190      case CODE_CONFIGACK:
191      case CODE_CONFIGREJ:
192      case CODE_CONFIGNAK:
193        (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL);
194        if (count < sizeof(struct fsmconfig))
195          log_Printf(fp->LogLevel, "  [EMPTY]\n");
196        break;
197    }
198  }
199
200  plen = sizeof(struct fsmheader) + count;
201  lh.code = code;
202  lh.id = id;
203  lh.length = htons(plen);
204  bp = m_get(plen, mtype);
205  memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
206  if (count)
207    memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
208  log_DumpBp(LogDEBUG, "fsm_Output", bp);
209  link_PushPacket(fp->link, bp, fp->bundle, LINK_QUEUES(fp->link) - 1,
210                  fp->proto);
211
212  if (code == CODE_CONFIGREJ)
213    lcp_SendIdentification(&fp->link->lcp);
214}
215
216static void
217FsmOpenNow(void *v)
218{
219  struct fsm *fp = (struct fsm *)v;
220
221  timer_Stop(&fp->OpenTimer);
222  if (fp->state <= ST_STOPPED) {
223    if (fp->state != ST_STARTING) {
224      /*
225       * In practice, we're only here in ST_STOPPED (when delaying the
226       * first config request) or ST_CLOSED (when openmode == 0).
227       *
228       * The ST_STOPPED bit is breaking the RFC already :-(
229       *
230       * According to the RFC (1661) state transition table, a TLS isn't
231       * required for an Open event when state == Closed, but the RFC
232       * must be wrong as TLS hasn't yet been called (since the last TLF)
233       * ie, Initial gets an `Up' event, Closing gets a RTA etc.
234       */
235      (*fp->fn->LayerStart)(fp);
236      (*fp->parent->LayerStart)(fp->parent->object, fp);
237    }
238    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
239    FsmSendConfigReq(fp);
240    NewState(fp, ST_REQSENT);
241  }
242}
243
244void
245fsm_Open(struct fsm *fp)
246{
247  switch (fp->state) {
248  case ST_INITIAL:
249    NewState(fp, ST_STARTING);
250    (*fp->fn->LayerStart)(fp);
251    (*fp->parent->LayerStart)(fp->parent->object, fp);
252    break;
253  case ST_CLOSED:
254    if (fp->open_mode == OPEN_PASSIVE) {
255      NewState(fp, ST_STOPPED);		/* XXX: This is a hack ! */
256    } else if (fp->open_mode > 0) {
257      if (fp->open_mode > 1)
258        log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n",
259                  fp->link->name, fp->open_mode);
260      NewState(fp, ST_STOPPED);		/* XXX: This is a not-so-bad hack ! */
261      timer_Stop(&fp->OpenTimer);
262      fp->OpenTimer.load = fp->open_mode * SECTICKS;
263      fp->OpenTimer.func = FsmOpenNow;
264      fp->OpenTimer.arg = (void *)fp;
265      timer_Start(&fp->OpenTimer);
266    } else
267      FsmOpenNow(fp);
268    break;
269  case ST_STOPPED:		/* XXX: restart option */
270  case ST_REQSENT:
271  case ST_ACKRCVD:
272  case ST_ACKSENT:
273  case ST_OPENED:		/* XXX: restart option */
274    break;
275  case ST_CLOSING:		/* XXX: restart option */
276  case ST_STOPPING:		/* XXX: restart option */
277    NewState(fp, ST_STOPPING);
278    break;
279  }
280}
281
282void
283fsm_Up(struct fsm *fp)
284{
285  switch (fp->state) {
286  case ST_INITIAL:
287    log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n",
288              fp->link->name);
289    NewState(fp, ST_CLOSED);
290    break;
291  case ST_STARTING:
292    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
293    FsmSendConfigReq(fp);
294    NewState(fp, ST_REQSENT);
295    break;
296  default:
297    log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n",
298              fp->link->name, State2Nam(fp->state));
299    break;
300  }
301}
302
303void
304fsm_Down(struct fsm *fp)
305{
306  switch (fp->state) {
307  case ST_CLOSED:
308    NewState(fp, ST_INITIAL);
309    break;
310  case ST_CLOSING:
311    /* This TLF contradicts the RFC (1661), which ``misses it out'' ! */
312    (*fp->fn->LayerFinish)(fp);
313    NewState(fp, ST_INITIAL);
314    (*fp->parent->LayerFinish)(fp->parent->object, fp);
315    break;
316  case ST_STOPPED:
317    NewState(fp, ST_STARTING);
318    (*fp->fn->LayerStart)(fp);
319    (*fp->parent->LayerStart)(fp->parent->object, fp);
320    break;
321  case ST_STOPPING:
322  case ST_REQSENT:
323  case ST_ACKRCVD:
324  case ST_ACKSENT:
325    NewState(fp, ST_STARTING);
326    break;
327  case ST_OPENED:
328    (*fp->fn->LayerDown)(fp);
329    NewState(fp, ST_STARTING);
330    (*fp->parent->LayerDown)(fp->parent->object, fp);
331    break;
332  }
333}
334
335void
336fsm_Close(struct fsm *fp)
337{
338  switch (fp->state) {
339  case ST_STARTING:
340    (*fp->fn->LayerFinish)(fp);
341    NewState(fp, ST_INITIAL);
342    (*fp->parent->LayerFinish)(fp->parent->object, fp);
343    break;
344  case ST_STOPPED:
345    NewState(fp, ST_CLOSED);
346    break;
347  case ST_STOPPING:
348    NewState(fp, ST_CLOSING);
349    break;
350  case ST_OPENED:
351    (*fp->fn->LayerDown)(fp);
352    if (fp->state == ST_OPENED) {
353      FsmInitRestartCounter(fp, FSM_TRM_TIMER);
354      FsmSendTerminateReq(fp);
355      NewState(fp, ST_CLOSING);
356      (*fp->parent->LayerDown)(fp->parent->object, fp);
357    }
358    break;
359  case ST_REQSENT:
360  case ST_ACKRCVD:
361  case ST_ACKSENT:
362    FsmInitRestartCounter(fp, FSM_TRM_TIMER);
363    FsmSendTerminateReq(fp);
364    NewState(fp, ST_CLOSING);
365    break;
366  }
367}
368
369/*
370 *	Send functions
371 */
372static void
373FsmSendConfigReq(struct fsm *fp)
374{
375  if (fp->more.reqs-- > 0 && fp->restart-- > 0) {
376    (*fp->fn->SendConfigReq)(fp);
377    timer_Start(&fp->FsmTimer);		/* Start restart timer */
378  } else {
379    if (fp->more.reqs < 0)
380      log_Printf(LogPHASE, "%s: Too many %s REQs sent - abandoning "
381                 "negotiation\n", fp->link->name, fp->name);
382    lcp_SendIdentification(&fp->link->lcp);
383    fsm_Close(fp);
384  }
385}
386
387static void
388FsmSendTerminateReq(struct fsm *fp)
389{
390  fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0, MB_UNKNOWN);
391  (*fp->fn->SentTerminateReq)(fp);
392  timer_Start(&fp->FsmTimer);	/* Start restart timer */
393  fp->restart--;		/* Decrement restart counter */
394}
395
396/*
397 *	Timeout actions
398 */
399static void
400FsmTimeout(void *v)
401{
402  struct fsm *fp = (struct fsm *)v;
403
404  if (fp->restart) {
405    switch (fp->state) {
406    case ST_CLOSING:
407    case ST_STOPPING:
408      FsmSendTerminateReq(fp);
409      break;
410    case ST_REQSENT:
411    case ST_ACKSENT:
412      FsmSendConfigReq(fp);
413      break;
414    case ST_ACKRCVD:
415      FsmSendConfigReq(fp);
416      NewState(fp, ST_REQSENT);
417      break;
418    }
419    timer_Start(&fp->FsmTimer);
420  } else {
421    switch (fp->state) {
422    case ST_CLOSING:
423      (*fp->fn->LayerFinish)(fp);
424      NewState(fp, ST_CLOSED);
425      (*fp->parent->LayerFinish)(fp->parent->object, fp);
426      break;
427    case ST_STOPPING:
428      (*fp->fn->LayerFinish)(fp);
429      NewState(fp, ST_STOPPED);
430      (*fp->parent->LayerFinish)(fp->parent->object, fp);
431      break;
432    case ST_REQSENT:		/* XXX: 3p */
433    case ST_ACKSENT:
434    case ST_ACKRCVD:
435      (*fp->fn->LayerFinish)(fp);
436      NewState(fp, ST_STOPPED);
437      (*fp->parent->LayerFinish)(fp->parent->object, fp);
438      break;
439    }
440  }
441}
442
443static void
444FsmInitRestartCounter(struct fsm *fp, int what)
445{
446  timer_Stop(&fp->FsmTimer);
447  fp->FsmTimer.func = FsmTimeout;
448  fp->FsmTimer.arg = (void *)fp;
449  (*fp->fn->InitRestartCounter)(fp, what);
450}
451
452/*
453 * Actions when receive packets
454 */
455static void
456FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
457/* RCR */
458{
459  struct fsm_decode dec;
460  int plen, flen;
461  int ackaction = 0;
462
463  plen = m_length(bp);
464  flen = ntohs(lhp->length) - sizeof *lhp;
465  if (plen < flen) {
466    log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",
467	      fp->link->name, plen, flen);
468    m_freem(bp);
469    return;
470  }
471
472  /* Check and process easy case */
473  switch (fp->state) {
474  case ST_INITIAL:
475    if (fp->proto == PROTO_CCP && fp->link->lcp.fsm.state == ST_OPENED) {
476      /*
477       * ccp_SetOpenMode() leaves us in initial if we're disabling
478       * & denying everything.
479       */
480      bp = m_prepend(bp, lhp, sizeof *lhp, 2);
481      bp = proto_Prepend(bp, fp->proto, 0, 0);
482      bp = m_pullup(bp);
483      lcp_SendProtoRej(&fp->link->lcp, MBUF_CTOP(bp), bp->m_len);
484      m_freem(bp);
485      return;
486    }
487    /* Drop through */
488  case ST_STARTING:
489    log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n",
490              fp->link->name, State2Nam(fp->state));
491    m_freem(bp);
492    return;
493  case ST_CLOSED:
494    (*fp->fn->SendTerminateAck)(fp, lhp->id);
495    m_freem(bp);
496    return;
497  case ST_CLOSING:
498    log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n",
499              fp->link->name, State2Nam(fp->state));
500  case ST_STOPPING:
501    m_freem(bp);
502    return;
503  case ST_OPENED:
504    (*fp->fn->LayerDown)(fp);
505    (*fp->parent->LayerDown)(fp->parent->object, fp);
506    break;
507  }
508
509  bp = m_pullup(bp);
510  dec.ackend = dec.ack;
511  dec.nakend = dec.nak;
512  dec.rejend = dec.rej;
513  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec);
514  if (flen < sizeof(struct fsmconfig))
515    log_Printf(fp->LogLevel, "  [EMPTY]\n");
516
517  if (dec.nakend == dec.nak && dec.rejend == dec.rej)
518    ackaction = 1;
519
520  switch (fp->state) {
521  case ST_STOPPED:
522    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
523    /* Fall through */
524
525  case ST_OPENED:
526    FsmSendConfigReq(fp);
527    break;
528  }
529
530  if (dec.rejend != dec.rej)
531    fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej,
532               MB_UNKNOWN);
533  if (dec.nakend != dec.nak)
534    fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak,
535               MB_UNKNOWN);
536  if (ackaction)
537    fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack,
538               MB_UNKNOWN);
539
540  switch (fp->state) {
541  case ST_STOPPED:
542      /*
543       * According to the RFC (1661) state transition table, a TLS isn't
544       * required for a RCR when state == ST_STOPPED, but the RFC
545       * must be wrong as TLS hasn't yet been called (since the last TLF)
546       */
547    (*fp->fn->LayerStart)(fp);
548    (*fp->parent->LayerStart)(fp->parent->object, fp);
549    /* Fall through */
550
551  case ST_OPENED:
552    if (ackaction)
553      NewState(fp, ST_ACKSENT);
554    else
555      NewState(fp, ST_REQSENT);
556    break;
557  case ST_REQSENT:
558    if (ackaction)
559      NewState(fp, ST_ACKSENT);
560    break;
561  case ST_ACKRCVD:
562    if (ackaction) {
563      NewState(fp, ST_OPENED);
564      if ((*fp->fn->LayerUp)(fp))
565        (*fp->parent->LayerUp)(fp->parent->object, fp);
566      else {
567        (*fp->fn->LayerDown)(fp);
568        FsmInitRestartCounter(fp, FSM_TRM_TIMER);
569        FsmSendTerminateReq(fp);
570        NewState(fp, ST_CLOSING);
571        lcp_SendIdentification(&fp->link->lcp);
572      }
573    }
574    break;
575  case ST_ACKSENT:
576    if (!ackaction)
577      NewState(fp, ST_REQSENT);
578    break;
579  }
580  m_freem(bp);
581
582  if (dec.rejend != dec.rej && --fp->more.rejs <= 0) {
583    log_Printf(LogPHASE, "%s: Too many %s REJs sent - abandoning negotiation\n",
584               fp->link->name, fp->name);
585    lcp_SendIdentification(&fp->link->lcp);
586    fsm_Close(fp);
587  }
588
589  if (dec.nakend != dec.nak && --fp->more.naks <= 0) {
590    log_Printf(LogPHASE, "%s: Too many %s NAKs sent - abandoning negotiation\n",
591               fp->link->name, fp->name);
592    lcp_SendIdentification(&fp->link->lcp);
593    fsm_Close(fp);
594  }
595}
596
597static void
598FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
599/* RCA */
600{
601  switch (fp->state) {
602    case ST_CLOSED:
603    case ST_STOPPED:
604    (*fp->fn->SendTerminateAck)(fp, lhp->id);
605    break;
606  case ST_CLOSING:
607  case ST_STOPPING:
608    break;
609  case ST_REQSENT:
610    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
611    NewState(fp, ST_ACKRCVD);
612    break;
613  case ST_ACKRCVD:
614    FsmSendConfigReq(fp);
615    NewState(fp, ST_REQSENT);
616    break;
617  case ST_ACKSENT:
618    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
619    NewState(fp, ST_OPENED);
620    if ((*fp->fn->LayerUp)(fp))
621      (*fp->parent->LayerUp)(fp->parent->object, fp);
622    else {
623      (*fp->fn->LayerDown)(fp);
624      FsmInitRestartCounter(fp, FSM_TRM_TIMER);
625      FsmSendTerminateReq(fp);
626      NewState(fp, ST_CLOSING);
627      lcp_SendIdentification(&fp->link->lcp);
628    }
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  }
637  m_freem(bp);
638}
639
640static void
641FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
642/* RCN */
643{
644  struct fsm_decode dec;
645  int plen, flen;
646
647  plen = m_length(bp);
648  flen = ntohs(lhp->length) - sizeof *lhp;
649  if (plen < flen) {
650    m_freem(bp);
651    return;
652  }
653
654  /*
655   * Check and process easy case
656   */
657  switch (fp->state) {
658  case ST_INITIAL:
659  case ST_STARTING:
660    log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n",
661              fp->link->name, State2Nam(fp->state));
662    m_freem(bp);
663    return;
664  case ST_CLOSED:
665  case ST_STOPPED:
666    (*fp->fn->SendTerminateAck)(fp, lhp->id);
667    m_freem(bp);
668    return;
669  case ST_CLOSING:
670  case ST_STOPPING:
671    m_freem(bp);
672    return;
673  }
674
675  bp = m_pullup(bp);
676  dec.ackend = dec.ack;
677  dec.nakend = dec.nak;
678  dec.rejend = dec.rej;
679  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec);
680  if (flen < sizeof(struct fsmconfig))
681    log_Printf(fp->LogLevel, "  [EMPTY]\n");
682
683  switch (fp->state) {
684  case ST_REQSENT:
685  case ST_ACKSENT:
686    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
687    FsmSendConfigReq(fp);
688    break;
689  case ST_OPENED:
690    (*fp->fn->LayerDown)(fp);
691    FsmSendConfigReq(fp);
692    NewState(fp, ST_REQSENT);
693    (*fp->parent->LayerDown)(fp->parent->object, fp);
694    break;
695  case ST_ACKRCVD:
696    FsmSendConfigReq(fp);
697    NewState(fp, ST_REQSENT);
698    break;
699  }
700
701  m_freem(bp);
702}
703
704static void
705FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
706/* RTR */
707{
708  switch (fp->state) {
709  case ST_INITIAL:
710  case ST_STARTING:
711    log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n",
712              fp->link->name, State2Nam(fp->state));
713    break;
714  case ST_CLOSED:
715  case ST_STOPPED:
716  case ST_CLOSING:
717  case ST_STOPPING:
718  case ST_REQSENT:
719    (*fp->fn->SendTerminateAck)(fp, lhp->id);
720    break;
721  case ST_ACKRCVD:
722  case ST_ACKSENT:
723    (*fp->fn->SendTerminateAck)(fp, lhp->id);
724    NewState(fp, ST_REQSENT);
725    break;
726  case ST_OPENED:
727    (*fp->fn->LayerDown)(fp);
728    (*fp->fn->SendTerminateAck)(fp, lhp->id);
729    FsmInitRestartCounter(fp, FSM_TRM_TIMER);
730    timer_Start(&fp->FsmTimer);			/* Start restart timer */
731    fp->restart = 0;
732    NewState(fp, ST_STOPPING);
733    (*fp->parent->LayerDown)(fp->parent->object, fp);
734    /* A delayed ST_STOPPED is now scheduled */
735    break;
736  }
737  m_freem(bp);
738}
739
740static void
741FsmRecvTermAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
742/* RTA */
743{
744  switch (fp->state) {
745  case ST_CLOSING:
746    (*fp->fn->LayerFinish)(fp);
747    NewState(fp, ST_CLOSED);
748    (*fp->parent->LayerFinish)(fp->parent->object, fp);
749    break;
750  case ST_STOPPING:
751    (*fp->fn->LayerFinish)(fp);
752    NewState(fp, ST_STOPPED);
753    (*fp->parent->LayerFinish)(fp->parent->object, fp);
754    break;
755  case ST_ACKRCVD:
756    NewState(fp, ST_REQSENT);
757    break;
758  case ST_OPENED:
759    (*fp->fn->LayerDown)(fp);
760    FsmSendConfigReq(fp);
761    NewState(fp, ST_REQSENT);
762    (*fp->parent->LayerDown)(fp->parent->object, fp);
763    break;
764  }
765  m_freem(bp);
766}
767
768static void
769FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
770/* RCJ */
771{
772  struct fsm_decode dec;
773  int plen, flen;
774
775  plen = m_length(bp);
776  flen = ntohs(lhp->length) - sizeof *lhp;
777  if (plen < flen) {
778    m_freem(bp);
779    return;
780  }
781
782  lcp_SendIdentification(&fp->link->lcp);
783
784  /*
785   * Check and process easy case
786   */
787  switch (fp->state) {
788  case ST_INITIAL:
789  case ST_STARTING:
790    log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n",
791              fp->link->name, State2Nam(fp->state));
792    m_freem(bp);
793    return;
794  case ST_CLOSED:
795  case ST_STOPPED:
796    (*fp->fn->SendTerminateAck)(fp, lhp->id);
797    m_freem(bp);
798    return;
799  case ST_CLOSING:
800  case ST_STOPPING:
801    m_freem(bp);
802    return;
803  }
804
805  bp = m_pullup(bp);
806  dec.ackend = dec.ack;
807  dec.nakend = dec.nak;
808  dec.rejend = dec.rej;
809  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec);
810  if (flen < sizeof(struct fsmconfig))
811    log_Printf(fp->LogLevel, "  [EMPTY]\n");
812
813  switch (fp->state) {
814  case ST_REQSENT:
815  case ST_ACKSENT:
816    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
817    FsmSendConfigReq(fp);
818    break;
819  case ST_OPENED:
820    (*fp->fn->LayerDown)(fp);
821    FsmSendConfigReq(fp);
822    NewState(fp, ST_REQSENT);
823    (*fp->parent->LayerDown)(fp->parent->object, fp);
824    break;
825  case ST_ACKRCVD:
826    FsmSendConfigReq(fp);
827    NewState(fp, ST_REQSENT);
828    break;
829  }
830  m_freem(bp);
831}
832
833static void
834FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
835{
836  m_freem(bp);
837}
838
839static void
840FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
841{
842  struct physical *p = link2physical(fp->link);
843  u_short proto;
844
845  if (m_length(bp) < 2) {
846    m_freem(bp);
847    return;
848  }
849  bp = mbuf_Read(bp, &proto, 2);
850  proto = ntohs(proto);
851  log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n",
852            fp->link->name, proto, hdlc_Protocol2Nam(proto));
853
854  switch (proto) {
855  case PROTO_LQR:
856    if (p)
857      lqr_Stop(p, LQM_LQR);
858    else
859      log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n",
860                fp->link->name);
861    break;
862  case PROTO_CCP:
863    if (fp->proto == PROTO_LCP) {
864      fp = &fp->link->ccp.fsm;
865      /* Despite the RFC (1661), don't do an out-of-place TLF */
866      /* (*fp->fn->LayerFinish)(fp); */
867      switch (fp->state) {
868      case ST_CLOSED:
869      case ST_CLOSING:
870        NewState(fp, ST_CLOSED);
871      default:
872        NewState(fp, ST_STOPPED);
873        break;
874      }
875      /* See above */
876      /* (*fp->parent->LayerFinish)(fp->parent->object, fp); */
877    }
878    break;
879  case PROTO_IPCP:
880    if (fp->proto == PROTO_LCP) {
881      log_Printf(LogPHASE, "%s: IPCP protocol reject closes IPCP !\n",
882                fp->link->name);
883      fsm_Close(&fp->bundle->ncp.ipcp.fsm);
884    }
885    break;
886  case PROTO_MP:
887    if (fp->proto == PROTO_LCP) {
888      struct lcp *lcp = fsm2lcp(fp);
889
890      if (lcp->want_mrru && lcp->his_mrru) {
891        log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n",
892                  fp->link->name);
893        fsm_Close(fp);
894      }
895    }
896    break;
897  }
898  m_freem(bp);
899}
900
901static void
902FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
903{
904  struct lcp *lcp = fsm2lcp(fp);
905  u_char *cp;
906  u_int32_t magic;
907
908  bp = m_pullup(bp);
909  m_settype(bp, MB_ECHOIN);
910
911  if (lcp && ntohs(lhp->length) - sizeof *lhp >= 4) {
912    cp = MBUF_CTOP(bp);
913    ua_ntohl(cp, &magic);
914    if (magic != lcp->his_magic) {
915      log_Printf(fp->LogLevel, "%s: RecvEchoReq: magic 0x%08lx is wrong,"
916                 " expecting 0x%08lx\n", fp->link->name, (u_long)magic,
917                 (u_long)lcp->his_magic);
918      /* XXX: We should send terminate request */
919    }
920    if (fp->state == ST_OPENED) {
921      ua_htonl(&lcp->want_magic, cp);		/* local magic */
922      fsm_Output(fp, CODE_ECHOREP, lhp->id, cp,
923                 ntohs(lhp->length) - sizeof *lhp, MB_ECHOOUT);
924    }
925  }
926  m_freem(bp);
927}
928
929static void
930FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
931{
932  if (fsm2lcp(fp))
933    bp = lqr_RecvEcho(fp, bp);
934
935  m_freem(bp);
936}
937
938static void
939FsmRecvDiscReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
940{
941  m_freem(bp);
942}
943
944static void
945FsmRecvIdent(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
946{
947  u_int32_t magic;
948  u_short len;
949  u_char *cp;
950
951  len = ntohs(lhp->length) - sizeof *lhp;
952  if (len >= 4) {
953    bp = m_pullup(m_append(bp, "", 1));
954    cp = MBUF_CTOP(bp);
955    ua_ntohl(cp, &magic);
956    if (magic != fp->link->lcp.his_magic)
957      log_Printf(fp->LogLevel, "%s: RecvIdent: magic 0x%08lx is wrong,"
958                 " expecting 0x%08lx\n", fp->link->name, (u_long)magic,
959                 (u_long)fp->link->lcp.his_magic);
960    cp[len] = '\0';
961    lcp_RecvIdentification(&fp->link->lcp, cp + 4);
962  }
963  m_freem(bp);
964}
965
966static void
967FsmRecvTimeRemain(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
968{
969  m_freem(bp);
970}
971
972static void
973FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
974{
975  (*fp->fn->RecvResetReq)(fp);
976  /*
977   * All sendable compressed packets are queued in the first (lowest
978   * priority) modem output queue.... dump 'em to the priority queue
979   * so that they arrive at the peer before our ResetAck.
980   */
981  link_SequenceQueue(fp->link);
982  fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0, MB_CCPOUT);
983  m_freem(bp);
984}
985
986static void
987FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
988{
989  (*fp->fn->RecvResetAck)(fp, lhp->id);
990  m_freem(bp);
991}
992
993void
994fsm_Input(struct fsm *fp, struct mbuf *bp)
995{
996  int len;
997  struct fsmheader lh;
998  const struct fsmcodedesc *codep;
999
1000  len = m_length(bp);
1001  if (len < sizeof(struct fsmheader)) {
1002    m_freem(bp);
1003    return;
1004  }
1005  bp = mbuf_Read(bp, &lh, sizeof lh);
1006
1007  if (ntohs(lh.length) > len) {
1008    log_Printf(LogWARN, "%s: Oops: Got %d bytes but %d byte payload "
1009               "- dropped\n", fp->link->name, len, (int)ntohs(lh.length));
1010    m_freem(bp);
1011    return;
1012  }
1013
1014  if (lh.code < fp->min_code || lh.code > fp->max_code ||
1015      lh.code > sizeof FsmCodes / sizeof *FsmCodes) {
1016    /*
1017     * Use a private id.  This is really a response-type packet, but we
1018     * MUST send a unique id for each REQ....
1019     */
1020    static u_char id;
1021
1022    bp = m_prepend(bp, &lh, sizeof lh, 0);
1023    bp = m_pullup(bp);
1024    fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->m_len, MB_UNKNOWN);
1025    m_freem(bp);
1026    return;
1027  }
1028
1029  codep = FsmCodes + lh.code - 1;
1030  if (lh.id != fp->reqid && codep->check_reqid &&
1031      Enabled(fp->bundle, OPT_IDCHECK)) {
1032    log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n",
1033	      fp->link->name, codep->name, lh.id, fp->reqid);
1034    return;
1035  }
1036
1037  log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n",
1038	    fp->link->name, codep->name, lh.id, State2Nam(fp->state));
1039
1040  if (codep->inc_reqid && (lh.id == fp->reqid ||
1041      (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid)))
1042    fp->reqid++;	/* That's the end of that ``exchange''.... */
1043
1044  (*codep->recv)(fp, &lh, bp);
1045}
1046
1047void
1048fsm_NullRecvResetReq(struct fsm *fp)
1049{
1050  log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n",
1051            fp->link->name);
1052}
1053
1054void
1055fsm_NullRecvResetAck(struct fsm *fp, u_char id)
1056{
1057  log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n",
1058            fp->link->name);
1059}
1060
1061void
1062fsm_Reopen(struct fsm *fp)
1063{
1064  if (fp->state == ST_OPENED) {
1065    (*fp->fn->LayerDown)(fp);
1066    FsmInitRestartCounter(fp, FSM_REQ_TIMER);
1067    FsmSendConfigReq(fp);
1068    NewState(fp, ST_REQSENT);
1069    (*fp->parent->LayerDown)(fp->parent->object, fp);
1070  }
1071}
1072
1073void
1074fsm2initial(struct fsm *fp)
1075{
1076  timer_Stop(&fp->FsmTimer);
1077  timer_Stop(&fp->OpenTimer);
1078  timer_Stop(&fp->StoppedTimer);
1079  if (fp->state == ST_STOPPED)
1080    fsm_Close(fp);
1081  if (fp->state > ST_INITIAL)
1082    fsm_Down(fp);
1083  if (fp->state > ST_INITIAL)
1084    fsm_Close(fp);
1085}
1086