File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / fsm.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:56:12 2016 UTC (7 years, 8 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, HEAD
mpd 5.8

    1: 
    2: /*
    3:  * fsm.c
    4:  *
    5:  * Written by Toshiharu OHNO <tony-o@iij.ad.jp>
    6:  * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved.
    7:  * See ``COPYRIGHT.iij''
    8:  * 
    9:  * Rewritten by Archie Cobbs <archie@freebsd.org>
   10:  * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
   11:  * See ``COPYRIGHT.whistle''
   12:  */
   13: 
   14: #include "ppp.h"
   15: #include "fsm.h"
   16: #include "ngfunc.h"
   17: #include "util.h"
   18: 
   19: /*
   20:  * DEFINITIONS
   21:  */
   22: 
   23:   #define FSM_MAXCONFIG		10
   24:   #define FSM_MAXNAK		10
   25:   #define FSM_MAX_OPTS		100
   26:   #define FSM_MAXTERMINATE	2
   27:   #define FSM_MAXFAILURE	5
   28: 
   29: /* FSM restart options */
   30: 
   31:   /* #define RESTART_OPENED */
   32:   /* #define RESTART_CLOSING */
   33:   /* #define RESTART_STOPPED */
   34: 
   35:   struct fsmcodedesc {
   36:     void	(*action)(Fsm fp, FsmHeader hdr, Mbuf bp);
   37:     const char	*name;
   38:   };
   39: 
   40: /* Size of REQ, ACK, NAK, and REJ buffers */
   41: 
   42:   #define REQ_BUFFER_SIZE	256
   43:   #define REJ_BUFFER_SIZE	256
   44:   #define ACK_BUFFER_SIZE	256
   45:   #define NAK_BUFFER_SIZE	256
   46: 
   47: /*
   48:  * INTERNAL FUNCTIONS
   49:  */
   50: 
   51:   static void	FsmNewState(Fsm f, enum fsm_state state);
   52: 
   53:   static void	FsmSendConfigReq(Fsm fp);
   54:   static void	FsmSendTerminateReq(Fsm fp);
   55:   static void	FsmSendTerminateAck(Fsm fp);
   56:   static void	FsmInitRestartCounter(Fsm fp, int value);
   57:   static void	FsmInitMaxFailure(Fsm fp, int value);
   58:   static void	FsmInitMaxConfig(Fsm fp, int value);
   59:   static void	FsmTimeout(void *arg);
   60: 
   61:   static void	FsmRecvConfigReq(Fsm fp, FsmHeader lhp, Mbuf bp);
   62:   static void	FsmRecvConfigAck(Fsm fp, FsmHeader lhp, Mbuf bp);
   63:   static void	FsmRecvConfigNak(Fsm fp, FsmHeader lhp, Mbuf bp);
   64:   static void	FsmRecvTermReq(Fsm fp, FsmHeader lhp, Mbuf bp);
   65:   static void	FsmRecvTermAck(Fsm fp, FsmHeader lhp, Mbuf bp);
   66:   static void	FsmRecvConfigRej(Fsm fp, FsmHeader lhp, Mbuf bp);
   67:   static void	FsmRecvCodeRej(Fsm fp, FsmHeader lhp, Mbuf bp);
   68:   static void	FsmRecvProtoRej(Fsm fp, FsmHeader lhp, Mbuf bp);
   69:   static void	FsmRecvEchoReq(Fsm fp, FsmHeader lhp, Mbuf bp);
   70:   static void	FsmRecvEchoRep(Fsm fp, FsmHeader lhp, Mbuf bp);
   71:   static void	FsmRecvDiscReq(Fsm fp, FsmHeader lhp, Mbuf bp);
   72:   static void	FsmRecvIdent(Fsm fp, FsmHeader lhp, Mbuf bp);
   73:   static void	FsmRecvTimeRemain(Fsm fp, FsmHeader lhp, Mbuf bp);
   74:   static void	FsmRecvResetReq(Fsm fp, FsmHeader lhp, Mbuf bp);
   75:   static void	FsmRecvResetAck(Fsm fp, FsmHeader lhp, Mbuf bp);
   76:   static void	FsmRecvVendor(Fsm fp, FsmHeader lhp, Mbuf bp);
   77:   static void	FsmRecvRxjPlus(Fsm fp);
   78: 
   79:   static void	FsmLayerUp(Fsm fp);
   80:   static void	FsmLayerDown(Fsm fp);
   81:   static void	FsmLayerStart(Fsm fp);
   82:   static void	FsmLayerFinish(Fsm fp);
   83: 
   84:   static Mbuf	FsmCheckMagic(Fsm fp, Mbuf bp);
   85:   static void	FsmEchoTimeout(void *arg);
   86:   static void	FsmDecodeBuffer(Fsm fp, u_char *buf, int size, int mode);
   87:   static int	FsmExtractOptions(Fsm fp, u_char *data,
   88: 		  int dlen, FsmOption opts, int max);
   89: 
   90: /*
   91:  * GLOBAL VARIABLES
   92:  */
   93: 
   94:   u_int		gAckSize, gNakSize, gRejSize;
   95: 
   96: /*
   97:  * INTERNAL VARIABLES
   98:  */
   99: 
  100: /*
  101:  * It's OK for these to be statically allocated, because we always
  102:  * do our work with them all in one whole step without stopping.
  103:  */
  104: 
  105:   static u_char	gRejBuf[REJ_BUFFER_SIZE];
  106:   static u_char	gAckBuf[ACK_BUFFER_SIZE];
  107:   static u_char	gNakBuf[NAK_BUFFER_SIZE];
  108: 
  109:   static const struct fsmcodedesc FsmCodes[] = {
  110:    { FsmRecvVendor,	"Vendor Packet" },
  111:    { FsmRecvConfigReq,  "Configure Request" },
  112:    { FsmRecvConfigAck,  "Configure Ack" },
  113:    { FsmRecvConfigNak,  "Configure Nak" },
  114:    { FsmRecvConfigRej,  "Configure Reject" },
  115:    { FsmRecvTermReq,    "Terminate Request" },
  116:    { FsmRecvTermAck,    "Terminate Ack" },
  117:    { FsmRecvCodeRej,    "Code Reject" },
  118:    { FsmRecvProtoRej,   "Protocol Reject" },
  119:    { FsmRecvEchoReq,    "Echo Request" },
  120:    { FsmRecvEchoRep,    "Echo Reply" },
  121:    { FsmRecvDiscReq,    "Discard Request" },
  122:    { FsmRecvIdent,      "Ident" },
  123:    { FsmRecvTimeRemain, "Time Remain" },
  124:    { FsmRecvResetReq,   "Reset Request" },
  125:    { FsmRecvResetAck,   "Reset Ack" },
  126:   };
  127: 
  128:   #define NUM_FSM_CODES	(sizeof(FsmCodes) / sizeof(*FsmCodes))
  129: 
  130: /*
  131:  * FsmInit()
  132:  *
  133:  * Initialize FSM structure and install some default values
  134:  */
  135: 
  136: void
  137: FsmInit(Fsm fp, FsmType type, void *arg)
  138: {
  139:   memset(fp, 0, sizeof(*fp));
  140:   fp->type = type;
  141:   fp->arg = arg;
  142:   fp->log = LG_FSM | type->log;
  143:   fp->log2 = LG_FSM | type->log2;
  144:   fp->conf.maxconfig = FSM_MAXCONFIG;
  145:   fp->conf.maxterminate = FSM_MAXTERMINATE;
  146:   fp->conf.maxfailure = FSM_MAXFAILURE;
  147:   fp->conf.check_magic = FALSE;
  148:   fp->conf.passive = FALSE;
  149:   fp->state = ST_INITIAL;
  150:   fp->reqid = 1;
  151:   fp->rejid = 1;
  152:   fp->echoid = 1;
  153: }
  154: 
  155: /*
  156:  * FsmInst()
  157:  *
  158:  * Instantiate FSM structure from template
  159:  */
  160: 
  161: void
  162: FsmInst(Fsm fp, Fsm fpt, void *arg)
  163: {
  164:     memcpy(fp, fpt, sizeof(*fp));
  165:     fp->arg = arg;
  166: }
  167: 
  168: /*
  169:  * FsmNewState()
  170:  *
  171:  * Change state of a FSM. Also, call the configuration routine
  172:  * if this is an appropriate time.
  173:  */
  174: 
  175: void
  176: FsmNewState(Fsm fp, enum fsm_state new)
  177: {
  178:   enum fsm_state	old;
  179: 
  180:   /* Log it */
  181:   Log(fp->log2, ("[%s] %s: state change %s --> %s",
  182:     Pref(fp), Fsm(fp), FsmStateName(fp->state), FsmStateName(new)));
  183: 
  184:   /* Change state and call protocol's own handler, if any */
  185:   old = fp->state;
  186:   if (fp->type->NewState)
  187:     (*fp->type->NewState)(fp, old, new);
  188:   fp->state = new;
  189:   if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED))
  190:     TimerStop(&fp->timer);
  191: 
  192:   /* Turn on/off keep-alive echo packets (if so configured) */
  193:   if (old == ST_OPENED)
  194:     TimerStop(&fp->echoTimer);
  195:   if (new == ST_OPENED && fp->conf.echo_int != 0) {
  196:     fp->quietCount = 0;
  197:     memset(&fp->idleStats, 0, sizeof(fp->idleStats));
  198:     TimerInit(&fp->echoTimer, "FsmKeepAlive",
  199:       fp->conf.echo_int * SECONDS, FsmEchoTimeout, fp);
  200:     TimerStartRecurring(&fp->echoTimer);
  201:   }
  202: }
  203: 
  204: /*
  205:  * FsmOutputMbuf()
  206:  *
  207:  * Send out a control packet with specified contents. Consumes the mbuf.
  208:  */
  209: 
  210: void
  211: FsmOutputMbuf(Fsm fp, u_int code, u_int id, Mbuf payload)
  212: {
  213:     Bund		b;
  214:     Mbuf		bp;
  215:     struct fsmheader	hdr;
  216: 
  217:     if (fp->type->link_layer)
  218: 	b = ((Link)fp->arg)->bund;
  219:     else
  220: 	b = (Bund)fp->arg;
  221: 
  222:     /* Build header */
  223:     hdr.id = id;
  224:     hdr.code = code;
  225:     hdr.length = htons(sizeof(hdr) + MBLEN(payload));
  226: 
  227:     /* Prepend to payload */
  228:     bp = mbcopyback(payload, -(int)sizeof(hdr), &hdr, sizeof(hdr));
  229: 
  230:     /* Send it out */
  231:     if (fp->type->link_layer) {
  232: 	NgFuncWritePppFrameLink((Link)fp->arg, fp->type->proto, bp);
  233:     } else {
  234: 	NgFuncWritePppFrame(b, NG_PPP_BUNDLE_LINKNUM, fp->type->proto, bp);
  235:     }
  236: }
  237: 
  238: /*
  239:  * FsmOutput()
  240:  *
  241:  * Send out a control packet with specified contents
  242:  */
  243: 
  244: void
  245: FsmOutput(Fsm fp, u_int code, u_int id, u_char *ptr, int len)
  246: {
  247:   Mbuf	bp;
  248: 
  249:   bp = (len > 0) ? mbcopyback(NULL, 0, ptr, len) : NULL;
  250:   FsmOutputMbuf(fp, code, id, bp);
  251: }
  252: 
  253: /*
  254:  * FsmOpen()
  255:  *
  256:  * XXX The use of the restart option should probably be
  257:  * XXX configured per FSM via the initialization structure.
  258:  * XXX For now, we just make it mandatory via #ifdef's.
  259:  */
  260: 
  261: void
  262: FsmOpen(Fsm fp)
  263: {
  264:   Log(fp->log2, ("[%s] %s: Open event", Pref(fp), Fsm(fp)));
  265:   switch (fp->state) {
  266:     case ST_INITIAL:
  267:       FsmNewState(fp, ST_STARTING);
  268:       FsmLayerStart(fp);
  269:       break;
  270:     case ST_STARTING:
  271:       break;
  272:     case ST_CLOSED:
  273:       if (fp->type->Configure)
  274: 	(*fp->type->Configure)(fp);
  275:       FsmNewState(fp, ST_REQSENT);
  276:       FsmLayerStart(fp);		/* Missing in RFC 1661 */
  277:       FsmInitRestartCounter(fp, fp->conf.maxconfig);
  278:       FsmInitMaxFailure(fp, fp->conf.maxfailure);
  279:       FsmInitMaxConfig(fp, fp->conf.maxconfig);
  280:       FsmSendConfigReq(fp);
  281:       break;
  282:     case ST_REQSENT:
  283:     case ST_ACKRCVD:
  284:     case ST_ACKSENT:
  285:       break;
  286: 
  287:     case ST_OPENED:
  288: #ifdef RESTART_OPENED
  289:       FsmDown(fp);
  290:       FsmUp(fp);
  291: #endif
  292:       break;
  293: 
  294:     case ST_CLOSING:
  295:       FsmNewState(fp, ST_STOPPING);
  296:     case ST_STOPPING:
  297: #ifdef RESTART_CLOSING
  298:       FsmDown(fp);
  299:       FsmUp(fp);
  300: #endif
  301:       break;
  302: 
  303:     case ST_STOPPED:
  304: #ifdef RESTART_STOPPED
  305:       FsmDown(fp);
  306:       FsmUp(fp);
  307: #endif
  308:       break;
  309:   }
  310: }
  311: 
  312: void
  313: FsmUp(Fsm fp)
  314: {
  315:   Log(fp->log2, ("[%s] %s: Up event", Pref(fp), Fsm(fp)));
  316:   switch (fp->state) {
  317:     case ST_INITIAL:
  318:       FsmNewState(fp, ST_CLOSED);
  319:       break;
  320:     case ST_STARTING:
  321:       if (fp->type->Configure)
  322: 	(*fp->type->Configure)(fp);
  323:       FsmNewState(fp, ST_REQSENT);
  324:       FsmInitRestartCounter(fp, fp->conf.maxconfig);
  325:       FsmInitMaxFailure(fp, fp->conf.maxfailure);
  326:       FsmInitMaxConfig(fp, fp->conf.maxconfig);
  327:       FsmSendConfigReq(fp);
  328:       break;
  329:     default:
  330:       Log(fp->log2, ("[%s] %s: Oops, UP at %s",
  331: 	Pref(fp), Fsm(fp), FsmStateName(fp->state)));
  332:       break;
  333:   }
  334: }
  335: 
  336: void
  337: FsmDown(Fsm fp)
  338: {
  339:   Log(fp->log2, ("[%s] %s: Down event", Pref(fp), Fsm(fp)));
  340:   switch (fp->state) {
  341:     case ST_CLOSING:
  342:       FsmLayerFinish(fp);		/* Missing in RFC 1661 */
  343:       /* fall through */
  344:     case ST_CLOSED:
  345:       FsmNewState(fp, ST_INITIAL);
  346:       break;
  347:     case ST_STOPPED:
  348:       FsmNewState(fp, ST_STARTING);
  349:       FsmLayerStart(fp);
  350:       break;
  351:     case ST_STOPPING:
  352:     case ST_REQSENT:
  353:     case ST_ACKRCVD:
  354:     case ST_ACKSENT:
  355:       FsmNewState(fp, ST_STARTING);
  356:       if (fp->type->UnConfigure)
  357: 	(*fp->type->UnConfigure)(fp);
  358:       break;
  359:     case ST_OPENED:
  360:       FsmNewState(fp, ST_STARTING);
  361:       FsmLayerDown(fp);
  362:       if (fp->type->UnConfigure)
  363: 	(*fp->type->UnConfigure)(fp);
  364:       break;
  365:     default:
  366:       break;
  367:   }
  368: }
  369: 
  370: void
  371: FsmClose(Fsm fp)
  372: {
  373:   Log(fp->log2, ("[%s] %s: Close event", Pref(fp), Fsm(fp)));
  374:   switch (fp->state) {
  375:     case ST_STARTING:
  376:       FsmNewState(fp, ST_INITIAL);
  377:       FsmLayerFinish(fp);
  378:       break;
  379:     case ST_STOPPED:
  380:       FsmNewState(fp, ST_CLOSED);
  381:       break;
  382:     case ST_STOPPING:
  383:       FsmNewState(fp, ST_CLOSING);
  384:       break;
  385:     case ST_OPENED:
  386:       FsmNewState(fp, ST_CLOSING);
  387:       FsmInitRestartCounter(fp, fp->conf.maxterminate);
  388:       FsmSendTerminateReq(fp);
  389:       FsmLayerDown(fp);
  390:       if (fp->type->UnConfigure)
  391: 	(*fp->type->UnConfigure)(fp);
  392:       break;
  393:     case ST_REQSENT:
  394:     case ST_ACKRCVD:
  395:     case ST_ACKSENT:
  396:       FsmNewState(fp, ST_CLOSING);
  397:       FsmInitRestartCounter(fp, fp->conf.maxterminate);
  398:       FsmSendTerminateReq(fp);
  399:       if (fp->type->UnConfigure)
  400: 	(*fp->type->UnConfigure)(fp);
  401:       break;
  402:     default:
  403:       break;
  404:   }
  405: }
  406: 
  407: /*
  408:  * Send functions
  409:  */
  410: 
  411: static void
  412: FsmSendConfigReq(Fsm fp)
  413: {
  414:   u_char	reqBuf[REQ_BUFFER_SIZE];
  415:   u_char	*cp;
  416: 
  417:   /* Build and display config request */
  418:   Log(fp->log, ("[%s] %s: SendConfigReq #%d", Pref(fp), Fsm(fp), fp->reqid));
  419:   cp = (*fp->type->BuildConfigReq)(fp, reqBuf);
  420:   FsmDecodeBuffer(fp, reqBuf, cp - reqBuf, MODE_NOP);
  421: 
  422:   /* Send it */
  423:   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, reqBuf, cp - reqBuf);
  424: 
  425:   /* Restart restart timer and decrement restart counter */
  426:   TimerStart(&fp->timer);
  427:   fp->restart--;
  428:   fp->config--;
  429: }
  430: 
  431: static void
  432: FsmSendTerminateReq(Fsm fp)
  433: {
  434:   Log(fp->log, ("[%s] %s: SendTerminateReq #%d", Pref(fp), Fsm(fp), fp->reqid));
  435:   FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
  436:   if (fp->type->SendTerminateReq)
  437:     (*fp->type->SendTerminateReq)(fp);
  438:   TimerStart(&fp->timer);	/* Restart restart timer */
  439:   fp->restart--;		/* Decrement restart counter */
  440: }
  441: 
  442: static void
  443: FsmSendTerminateAck(Fsm fp)
  444: {
  445:   Log(fp->log, ("[%s] %s: SendTerminateAck #%d", Pref(fp), Fsm(fp), fp->reqid));
  446:   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
  447:   if (fp->type->SendTerminateAck)
  448:     (*fp->type->SendTerminateAck)(fp);
  449: }
  450: 
  451: static void
  452: FsmSendConfigAck(Fsm fp, FsmHeader lhp, u_char *option, int count)
  453: {
  454:   Log(fp->log, ("[%s] %s: SendConfigAck #%d", Pref(fp), Fsm(fp), lhp->id));
  455:   FsmDecodeBuffer(fp, option, count, MODE_NOP);
  456:   FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
  457: }
  458: 
  459: static void
  460: FsmSendConfigRej(Fsm fp, FsmHeader lhp, u_char *option, int count)
  461: {
  462:   Log(fp->log, ("[%s] %s: SendConfigRej #%d", Pref(fp), Fsm(fp), lhp->id));
  463:   FsmDecodeBuffer(fp, option, count, MODE_NOP);
  464:   FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
  465:   fp->failure--;
  466: }
  467: 
  468: static void
  469: FsmSendConfigNak(Fsm fp, FsmHeader lhp, u_char *option, int count)
  470: {
  471:   Log(fp->log, ("[%s] %s: SendConfigNak #%d", Pref(fp), Fsm(fp), lhp->id));
  472:   FsmDecodeBuffer(fp, option, count, MODE_NOP);
  473:   FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
  474:   fp->failure--;
  475: }
  476: 
  477: /*
  478:  * Timeout actions
  479:  */
  480: 
  481: static void
  482: FsmTimeout(void *arg)
  483: {
  484:   Fsm	fp = (Fsm) arg;
  485: 
  486:   if (fp->restart > 0) {	/* TO+ */
  487:     switch (fp->state) {
  488:       case ST_CLOSING:
  489:       case ST_STOPPING:
  490: 	FsmSendTerminateReq(fp);
  491: 	break;
  492:       case ST_REQSENT:
  493:       case ST_ACKSENT:
  494: 	FsmSendConfigReq(fp);
  495: 	break;
  496:       case ST_ACKRCVD:
  497: 	FsmNewState(fp, ST_REQSENT);
  498: 	FsmSendConfigReq(fp);
  499: 	break;
  500:       default:
  501: 	break;
  502:     }
  503:   } else {				/* TO- */
  504:     switch (fp->state) {
  505:       case ST_CLOSING:
  506: 	FsmNewState(fp, ST_CLOSED);
  507: 	FsmLayerFinish(fp);
  508: 	break;
  509:       case ST_STOPPING:
  510: 	FsmNewState(fp, ST_STOPPED);
  511: 	FsmLayerFinish(fp);
  512: 	break;
  513:       case ST_REQSENT:
  514:       case ST_ACKSENT:
  515:       case ST_ACKRCVD:
  516: 	FsmFailure(fp, FAIL_NEGOT_FAILURE);
  517: 	break;
  518:       default:
  519:         break;
  520:     }
  521:   }
  522: }
  523: 
  524: void
  525: FsmInitRestartCounter(Fsm fp, int value)
  526: {
  527:   const int	retry = fp->type->link_layer ?
  528: 			((Link)(fp->arg))->conf.retry_timeout : 
  529: 			((Bund)(fp->arg))->conf.retry_timeout;
  530: 
  531:   TimerStop(&fp->timer);
  532:   TimerInit(&fp->timer,
  533:     fp->type->name, retry * SECONDS, FsmTimeout, (void *) fp);
  534:   fp->restart = value;
  535: }
  536: 
  537: void
  538: FsmInitMaxFailure(Fsm fp, int value)
  539: {
  540:   fp->failure = value;
  541: }
  542: 
  543: void
  544: FsmInitMaxConfig(Fsm fp, int value)
  545: {
  546:   fp->config = value;
  547: }
  548: 
  549: /*
  550:  * Actions that happen when we receive packets
  551:  */
  552: 
  553: /* RCR */
  554: 
  555: static void
  556: FsmRecvConfigReq(Fsm fp, FsmHeader lhp, Mbuf bp)
  557: {
  558:   int	fullyAcked;
  559: 
  560:   /* Check and process easy cases */
  561:   switch (fp->state) {
  562:     case ST_INITIAL:
  563:     case ST_STARTING:
  564:       Log(fp->log2, ("[%s] %s: Oops, RCR in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
  565:       mbfree(bp);
  566:       return;
  567:     case ST_CLOSED:
  568:       FsmSendTerminateAck(fp);
  569:       mbfree(bp);
  570:       return;
  571:     case ST_STOPPED:
  572:       if (fp->type->Configure)
  573: 	(*fp->type->Configure)(fp);
  574:       break;
  575:     case ST_CLOSING:
  576:     case ST_STOPPING:
  577:       mbfree(bp);
  578:       return;
  579:     default:
  580:       break;
  581:   }
  582: 
  583:   /* Decode packet */
  584:   FsmDecodeBuffer(fp, MBDATA(bp), MBLEN(bp), MODE_REQ);
  585: 
  586:   /* State specific actions */
  587:   switch (fp->state) {
  588:     case ST_OPENED:
  589:       FsmLayerDown(fp);
  590:       FsmSendConfigReq(fp);
  591:       break;
  592:     case ST_STOPPED:
  593:       FsmLayerStart(fp);		/* Missing in RFC 1661 */
  594:       FsmInitRestartCounter(fp, fp->conf.maxconfig);
  595:       FsmInitMaxFailure(fp, fp->conf.maxfailure);
  596:       FsmInitMaxConfig(fp, fp->conf.maxconfig);
  597:       FsmSendConfigReq(fp);
  598:       break;
  599:     default:
  600:       break;
  601:   }
  602: 
  603:   /* What did we think of packet? */
  604:   fullyAcked = (gNakSize == 0 && gRejSize == 0);
  605:   if (fullyAcked)
  606:     FsmSendConfigAck(fp, lhp, gAckBuf, gAckSize);
  607:   else {
  608:     if (fp->failure <= 0) {
  609:       Log(fp->log, ("[%s] %s: not converging", Pref(fp), Fsm(fp)));
  610:       FsmFailure(fp, FAIL_NEGOT_FAILURE);
  611:       mbfree(bp);
  612:       return;
  613:     } else {
  614:       if (gRejSize)
  615: 	FsmSendConfigRej(fp, lhp, gRejBuf, gRejSize);
  616:       else if (gNakSize)
  617: 	FsmSendConfigNak(fp, lhp, gNakBuf, gNakSize);
  618:     }
  619:   }
  620: 
  621:   /* Continue with state transition */
  622:   switch (fp->state) {
  623:     case ST_STOPPED:
  624:     case ST_OPENED:
  625:       if (fullyAcked)
  626: 	FsmNewState(fp, ST_ACKSENT);
  627:       else
  628: 	FsmNewState(fp, ST_REQSENT);
  629:       break;
  630:     case ST_REQSENT:
  631:       if (fullyAcked)
  632: 	FsmNewState(fp, ST_ACKSENT);
  633:       break;
  634:     case ST_ACKRCVD:
  635:       if (fullyAcked)
  636:       {
  637: 	FsmNewState(fp, ST_OPENED);
  638: 	FsmLayerUp(fp);
  639:       }
  640:       break;
  641:     case ST_ACKSENT:
  642:       if (!fullyAcked)
  643: 	FsmNewState(fp, ST_REQSENT);
  644:       break;
  645:     default:
  646:       break;
  647:   }
  648:   mbfree(bp);
  649: }
  650: 
  651: /* RCA */
  652: 
  653: static void
  654: FsmRecvConfigAck(Fsm fp, FsmHeader lhp, Mbuf bp)
  655: {
  656: 
  657:   /* Check sequence number */
  658:   if (lhp->id != (u_char) (fp->reqid - 1)) {
  659:     Log(fp->log, ("[%s]   Wrong id#, expecting %d", Pref(fp), (u_char) (fp->reqid - 1)));
  660:     mbfree(bp);
  661:     return;
  662:   }
  663: 
  664:   /* XXX We should verify the contents are equal to our last sent config-req */
  665: 
  666:   /* Decode packet */
  667:   FsmDecodeBuffer(fp, MBDATA(bp), MBLEN(bp), MODE_NOP);
  668: 
  669:   /* Do whatever */
  670:   switch (fp->state) {
  671:     case ST_CLOSED:
  672:     case ST_STOPPED:
  673:       FsmSendTerminateAck(fp);
  674:       break;
  675:     case ST_CLOSING:
  676:     case ST_STOPPING:
  677:       break;
  678:     case ST_REQSENT:
  679:       FsmNewState(fp, ST_ACKRCVD);
  680:       FsmInitRestartCounter(fp, fp->conf.maxconfig);
  681:       FsmInitMaxFailure(fp, fp->conf.maxfailure);
  682:       FsmInitMaxConfig(fp, fp->conf.maxconfig);
  683:       TimerStart(&fp->timer);		/* Start restart timer */
  684:       break;
  685:     case ST_ACKRCVD:
  686:       FsmNewState(fp, ST_REQSENT);
  687:       FsmSendConfigReq(fp);
  688:       break;
  689:     case ST_ACKSENT:
  690:       FsmNewState(fp, ST_OPENED);
  691:       FsmInitRestartCounter(fp, fp->conf.maxconfig);
  692:       FsmInitMaxFailure(fp, fp->conf.maxfailure);
  693:       FsmInitMaxConfig(fp, fp->conf.maxconfig);
  694:       FsmLayerUp(fp);
  695:       break;
  696:     case ST_OPENED:
  697:       FsmNewState(fp, ST_REQSENT);
  698:       FsmLayerDown(fp);
  699:       FsmSendConfigReq(fp);
  700:       break;
  701:     default:
  702:       break;
  703:   }
  704:   mbfree(bp);
  705: }
  706: 
  707: /* RCN */
  708: 
  709: static void
  710: FsmRecvConfigNak(Fsm fp, FsmHeader lhp, Mbuf bp)
  711: {
  712: 
  713:   /* Check sequence number */
  714:   if (lhp->id != (u_char) (fp->reqid - 1)) {
  715:     Log(fp->log, ("[%s]   Wrong id#, expecting %d", Pref(fp), (u_char) (fp->reqid - 1)));
  716:     mbfree(bp);
  717:     return;
  718:   }
  719: 
  720:   /* Check and process easy cases */
  721:   switch (fp->state) {
  722:     case ST_INITIAL:
  723:     case ST_STARTING:
  724:       Log(fp->log, ("[%s] %s: Oops, RCN in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
  725:       mbfree(bp);
  726:       return;
  727:     case ST_CLOSED:
  728:     case ST_STOPPED:
  729:       FsmSendTerminateAck(fp);
  730:       mbfree(bp);
  731:       return;
  732:     case ST_CLOSING:
  733:     case ST_STOPPING:
  734:       mbfree(bp);
  735:       return;
  736:     default:
  737:       break;
  738:   }
  739: 
  740:   /* Decode packet */
  741:   FsmDecodeBuffer(fp, MBDATA(bp), MBLEN(bp), MODE_NAK);
  742: 
  743:   /* Not converging? */
  744:   if (fp->config <= 0) {
  745:     Log(fp->log, ("[%s] %s: not converging", Pref(fp), Fsm(fp)));
  746:     FsmFailure(fp, FAIL_NEGOT_FAILURE);
  747:     mbfree(bp);
  748:     return;
  749:   }
  750: 
  751:   /* Do whatever */
  752:   switch (fp->state) {
  753:     case ST_REQSENT:
  754:     case ST_ACKSENT:
  755:       FsmInitRestartCounter(fp, fp->conf.maxconfig);
  756:       FsmSendConfigReq(fp);
  757:       break;
  758:     case ST_OPENED:
  759:       FsmLayerDown(fp);
  760:       /* fall through */
  761:     case ST_ACKRCVD:
  762:       FsmNewState(fp, ST_REQSENT);
  763:       FsmSendConfigReq(fp);
  764:       break;
  765:     default:
  766:       break;
  767:   }
  768:   mbfree(bp);
  769: }
  770: 
  771: /* RCJ */
  772: 
  773: static void
  774: FsmRecvConfigRej(Fsm fp, FsmHeader lhp, Mbuf bp)
  775: {
  776: 
  777:   /* Check sequence number */
  778:   if (lhp->id != (u_char) (fp->reqid - 1)) {
  779:     Log(fp->log, ("[%s]   Wrong id#, expecting %d", Pref(fp), (u_char) (fp->reqid - 1)));
  780:     mbfree(bp);
  781:     return;
  782:   }
  783: 
  784:   /* XXX should verify contents are a subset of previously sent config-req */
  785: 
  786:   /* Check and process easy cases */
  787:   switch (fp->state) {
  788:     case ST_INITIAL:
  789:     case ST_STARTING:
  790:       Log(fp->log, ("[%s] %s: Oops, RCJ in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
  791:       mbfree(bp);
  792:       return;
  793:     case ST_CLOSED:
  794:     case ST_STOPPED:
  795:       FsmSendTerminateAck(fp);
  796:       mbfree(bp);
  797:       return;
  798:     case ST_CLOSING:
  799:     case ST_STOPPING:
  800:       mbfree(bp);
  801:       return;
  802:     default:
  803:       break;
  804:   }
  805: 
  806:   /* Decode packet */
  807:   FsmDecodeBuffer(fp, MBDATA(bp), MBLEN(bp), MODE_REJ);
  808: 
  809:   /* Not converging? */
  810:   if (fp->config <= 0) {
  811:     Log(fp->log, ("[%s] %s: not converging", Pref(fp), Fsm(fp)));
  812:     FsmFailure(fp, FAIL_NEGOT_FAILURE);
  813:     mbfree(bp);
  814:     return;
  815:   }
  816: 
  817:   /* Do whatever */
  818:   switch (fp->state) {
  819:     case ST_REQSENT:
  820:     case ST_ACKSENT:
  821:       FsmInitRestartCounter(fp, fp->conf.maxconfig);
  822:       FsmSendConfigReq(fp);
  823:       break;
  824:     case ST_OPENED:
  825:       FsmNewState(fp, ST_REQSENT);
  826:       FsmLayerDown(fp);
  827:       FsmSendConfigReq(fp);
  828:       break;
  829:     case ST_ACKRCVD:
  830:       FsmNewState(fp, ST_REQSENT);
  831:       FsmSendConfigReq(fp);
  832:       break;
  833:     default:
  834:       break;
  835:   }
  836:   mbfree(bp);
  837: }
  838: 
  839: /* RTR */
  840: 
  841: static void
  842: FsmRecvTermReq(Fsm fp, FsmHeader lhp, Mbuf bp)
  843: {
  844:   if (fp->type->link_layer) {
  845:     RecordLinkUpDownReason(NULL, (Link)(fp->arg), 0, STR_PEER_DISC, NULL);
  846:   }
  847:   switch (fp->state) {
  848:     case ST_INITIAL:
  849:     case ST_STARTING:
  850:       Log(fp->log, ("[%s] %s: Oops, RTR in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
  851:       break;
  852:     case ST_CLOSED:
  853:     case ST_STOPPED:
  854:     case ST_CLOSING:
  855:     case ST_STOPPING:
  856:     case ST_REQSENT:
  857:       FsmSendTerminateAck(fp);
  858:       break;
  859:     case ST_ACKRCVD:
  860:     case ST_ACKSENT:
  861:       FsmNewState(fp, ST_REQSENT);
  862:       FsmSendTerminateAck(fp);
  863:       break;
  864:     case ST_OPENED:
  865:       FsmNewState(fp, ST_STOPPING);
  866:       FsmSendTerminateAck(fp);
  867:       FsmLayerDown(fp);
  868:       FsmInitRestartCounter(fp, 0);	/* Zero restart counter */
  869:       TimerStart(&fp->timer);		/* Start restart timer */
  870:       if (fp->type->UnConfigure)
  871: 	(*fp->type->UnConfigure)(fp);
  872:       break;
  873:   }
  874:   mbfree(bp);
  875: }
  876: 
  877: /* RTA */
  878: 
  879: static void
  880: FsmRecvTermAck(Fsm fp, FsmHeader lhp, Mbuf bp)
  881: {
  882:   switch (fp->state) {
  883:     case ST_CLOSING:
  884:       FsmNewState(fp, ST_CLOSED);
  885:       FsmLayerFinish(fp);
  886:       break;
  887:     case ST_STOPPING:
  888:       FsmNewState(fp, ST_STOPPED);
  889:       FsmLayerFinish(fp);
  890:       break;
  891:     case ST_ACKRCVD:
  892:       FsmNewState(fp, ST_REQSENT);
  893:       break;
  894:     case ST_OPENED:
  895:       FsmNewState(fp, ST_REQSENT);
  896:       FsmLayerDown(fp);
  897:       FsmSendConfigReq(fp);
  898:       break;
  899:     default:
  900:       break;
  901:   }
  902:   mbfree(bp);
  903: }
  904: 
  905: /*
  906:  * FsmRecvCodeRej()
  907:  *
  908:  * By default, this is fatal for most codes
  909:  */
  910: 
  911: static void
  912: FsmRecvCodeRej(Fsm fp, FsmHeader lhp, Mbuf bp)
  913: {
  914:   u_char	code = 0;
  915:   int		fatal;
  916: 
  917:   /* Get code and log it */
  918:   bp = mbread(bp, &code, sizeof(code));
  919:   Log(fp->log, ("[%s] %s: code %s was rejected", Pref(fp), Fsm(fp), FsmCodeName(code)));
  920: 
  921:   /* Determine fatalness */
  922:   if (fp->type->RecvCodeRej)
  923:     fatal = (*fp->type->RecvCodeRej)(fp, code, bp);
  924:   else {
  925:     switch (code) {
  926:       case CODE_CONFIGREQ:
  927:       case CODE_CONFIGACK:
  928:       case CODE_CONFIGNAK:
  929:       case CODE_CONFIGREJ:
  930:       case CODE_TERMREQ:
  931:       case CODE_TERMACK:
  932:       case CODE_CODEREJ:
  933:       case CODE_PROTOREJ:
  934:       case CODE_ECHOREQ:
  935:       case CODE_ECHOREP:
  936:       case CODE_RESETREQ:
  937:       case CODE_RESETACK:
  938: 	fatal = TRUE;
  939: 	break;
  940:       case CODE_VENDOR:
  941:       case CODE_DISCREQ:
  942:       case CODE_IDENT:
  943:       case CODE_TIMEREM:
  944:       default:		/* if we don't know it, that makes two of us */
  945: 	fatal = FALSE;
  946: 	break;
  947:     }
  948:   }
  949: 
  950:   /* Possibly shut down as a result */
  951:   if (fatal)
  952:     FsmFailure(fp, FAIL_RECD_CODEREJ);		/* RXJ- */
  953:   else
  954:     FsmRecvRxjPlus(fp);
  955:   mbfree(bp);
  956: }
  957: 
  958: /*
  959:  * FsmRecvProtoRej()
  960:  *
  961:  * By default, this is non-fatal
  962:  */
  963: 
  964: static void
  965: FsmRecvProtoRej(Fsm fp, FsmHeader lhp, Mbuf bp)
  966: {
  967:   u_short	proto = 0;
  968:   int		fatal = FALSE;
  969: 
  970:   bp = mbread(bp, &proto, sizeof(proto));
  971:   proto = ntohs(proto);
  972:   Log(fp->log, ("[%s] %s: protocol %s was rejected", Pref(fp), Fsm(fp), ProtoName(proto)));
  973:   if (fp->state == ST_OPENED && fp->type->RecvProtoRej)
  974:     fatal = (*fp->type->RecvProtoRej)(fp, proto, bp);
  975:   if (fatal)
  976:     FsmFailure(fp, FAIL_RECD_PROTREJ);		/* RXJ- */
  977:   else
  978:     FsmRecvRxjPlus(fp);
  979:   mbfree(bp);
  980: }
  981: 
  982: /*
  983:  * FsmRecvRxjPlus()
  984:  */
  985: 
  986: static void
  987: FsmRecvRxjPlus(Fsm fp)				/* RXJ+ */
  988: {
  989:   switch (fp->state) {
  990:     case ST_ACKRCVD:
  991:       FsmNewState(fp, ST_REQSENT);
  992:       break;
  993:     default:
  994:       break;
  995:   }
  996: }
  997: 
  998: /*
  999:  * FsmFailure()
 1000:  *
 1001:  * Call this at any point if something fatal happens that is inherent
 1002:  * to the FSM itself, like a RXJ- event or negotiation failed to converge.
 1003:  * The action taken is like the RXJ- event.
 1004:  */
 1005: 
 1006: void
 1007: FsmFailure(Fsm fp, enum fsmfail reason)
 1008: {
 1009:   Log(fp->log, ("[%s] %s: %s", Pref(fp), Fsm(fp), FsmFailureStr(reason)));
 1010: 
 1011:   /* Let layer do any special handling of error code */
 1012:   if (fp->type->Failure)
 1013:     (*fp->type->Failure)(fp, reason);
 1014: 
 1015:   /* Shut this state machine down */
 1016:   switch (fp->state) {
 1017:     case ST_CLOSING:
 1018:       FsmNewState(fp, ST_CLOSED);
 1019:       /* fall through */
 1020:     case ST_CLOSED:
 1021:       FsmLayerFinish(fp);
 1022:       break;
 1023:     case ST_STOPPING:
 1024:       FsmNewState(fp, ST_STOPPED);
 1025:       FsmLayerFinish(fp);
 1026:       break;
 1027:     case ST_ACKRCVD:
 1028:     case ST_ACKSENT:
 1029:     case ST_REQSENT:
 1030:       FsmNewState(fp, ST_STOPPED);
 1031:       if (!fp->conf.passive)
 1032: 	FsmLayerFinish(fp);
 1033:       if (fp->type->UnConfigure)
 1034: 	(*fp->type->UnConfigure)(fp);
 1035:       break;
 1036: 
 1037:     /*
 1038:      * In the opened state, the peer FSM has somehow died or did something
 1039:      * horribly wrong to us. So the common sense action in this case is to 
 1040:      * bring the whole link down, rather than restarting just the FSM.
 1041:      * We do this by telling the lower layer to restart using tlf and tls
 1042:      * while also pretending that we got a DOWN event.
 1043:      */
 1044:     case ST_OPENED:
 1045:       FsmNewState(fp, ST_STOPPING);
 1046:       FsmInitRestartCounter(fp, fp->conf.maxterminate);
 1047:       FsmSendTerminateReq(fp);
 1048:       FsmLayerDown(fp);
 1049:       if (fp->type->UnConfigure)
 1050: 	(*fp->type->UnConfigure)(fp);
 1051:       break;
 1052: 
 1053:     /*
 1054:      * In the STOPPED state, then most likely the negotiation timed out
 1055:      * or didn't converge. Just wait for the DOWN event from the previously
 1056:      * issued tlf action.
 1057:      */
 1058:     case ST_STOPPED:
 1059:       if (!fp->conf.passive)
 1060: 	FsmLayerFinish(fp);
 1061:       break;
 1062:     default:
 1063:       break;
 1064:   }
 1065: }
 1066: 
 1067: /*
 1068:  * FsmFailureStr()
 1069:  */
 1070: 
 1071: const char *
 1072: FsmFailureStr(enum fsmfail reason)
 1073: {
 1074:   const char	*string = NULL;
 1075: 
 1076:   switch (reason) {
 1077:     case FAIL_NEGOT_FAILURE:
 1078:       string = STR_FAIL_NEGOT_FAILURE;
 1079:       break;
 1080:     case FAIL_RECD_BADMAGIC:
 1081:       string = STR_FAIL_RECD_BADMAGIC;
 1082:       break;
 1083:     case FAIL_RECD_CODEREJ:
 1084:       string = STR_FAIL_RECD_CODEREJ;
 1085:       break;
 1086:     case FAIL_RECD_PROTREJ:
 1087:       string = STR_FAIL_RECD_PROTREJ;
 1088:       break;
 1089:     case FAIL_WAS_PROTREJ:
 1090:       string = STR_FAIL_WAS_PROTREJ;
 1091:       break;
 1092:     case FAIL_ECHO_TIMEOUT:
 1093:       string = STR_FAIL_ECHO_TIMEOUT;
 1094:       break;
 1095:     case FAIL_CANT_ENCRYPT:
 1096:       string = STR_FAIL_CANT_ENCRYPT;
 1097:       break;
 1098:     default:
 1099:       assert(0);
 1100:   }
 1101:   return(string);
 1102: }
 1103: 
 1104: /*
 1105:  * FsmSendEchoReq()
 1106:  *
 1107:  * Send an echo request containing the supplied payload data.
 1108:  * Consumes the mbuf.
 1109:  */
 1110: 
 1111: void
 1112: FsmSendEchoReq(Fsm fp, Mbuf payload)
 1113: {
 1114:   u_int32_t	const self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
 1115:   Mbuf		bp;
 1116: 
 1117:   if (fp->state != ST_OPENED)
 1118:     return;
 1119: 
 1120:   /* Prepend my magic number */
 1121:   bp = mbcopyback(payload, -(int)sizeof(self_magic), &self_magic, sizeof(self_magic));
 1122: 
 1123:   /* Send it */
 1124:   Log(LG_ECHO, ("[%s] %s: SendEchoReq #%d", Pref(fp), Fsm(fp), fp->echoid));
 1125:   FsmOutputMbuf(fp, CODE_ECHOREQ, fp->echoid++, bp);
 1126: }
 1127: 
 1128: /*
 1129:  * FsmSendIdent()
 1130:  *
 1131:  * Send an LCP ident packet.
 1132:  */
 1133: 
 1134: void
 1135: FsmSendIdent(Fsm fp, const char *ident)
 1136: {
 1137:   u_int32_t	self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
 1138:   const int	len = strlen(ident) + 1;	/* include NUL to be nice */
 1139:   Mbuf		bp;
 1140: 
 1141:   /* Leave magic zero unless fully opened, as IDENT can be sent anytime */
 1142:   if (fp->state != ST_OPENED)
 1143:     self_magic = 0;
 1144: 
 1145:   /* Prepend my magic number */
 1146:   bp = mbcopyback(NULL, 0, (u_char *) &self_magic, sizeof(self_magic));
 1147:   bp = mbcopyback(bp, sizeof(self_magic), ident, len);
 1148: 
 1149:   /* Send it */
 1150:   Log(fp->log2, ("[%s] %s: SendIdent #%d", Pref(fp), Fsm(fp), fp->echoid));
 1151:   ShowMesg(fp->log2, Pref(fp), ident, len);
 1152:   FsmOutputMbuf(fp, CODE_IDENT, fp->echoid++, bp);
 1153: }
 1154: 
 1155: /*
 1156:  * FsmSendTimeRemaining()
 1157:  *
 1158:  * Send an LCP Time-Remaining packet.
 1159:  */
 1160: 
 1161: void
 1162: FsmSendTimeRemaining(Fsm fp, u_int seconds)
 1163: {
 1164:   u_int32_t	self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
 1165:   u_int32_t	data = htonl(seconds);
 1166:   Mbuf		bp;
 1167: 
 1168:   /* Leave magic zero unless fully opened, as IDENT can be sent anytime */
 1169:   if (fp->state != ST_OPENED)
 1170:     self_magic = 0;
 1171: 
 1172:   /* Prepend my magic number */
 1173:   bp = mbcopyback(NULL, 0, (u_char *) &self_magic, sizeof(self_magic));
 1174:   bp = mbcopyback(bp, sizeof(self_magic), &data, 4);
 1175: 
 1176:   /* Send it */
 1177:   Log(fp->log2, ("[%s] %s: SendTimeRemaining #%d", Pref(fp), Fsm(fp), fp->echoid));
 1178:   Log(fp->log2, ("[%s]   %u seconds remain", Pref(fp), seconds));
 1179:   FsmOutputMbuf(fp, CODE_TIMEREM, fp->echoid++, bp);
 1180: }
 1181: 
 1182: /*
 1183:  * FsmRecvEchoReq()
 1184:  */
 1185: 
 1186: static void
 1187: FsmRecvEchoReq(Fsm fp, FsmHeader lhp, Mbuf bp)
 1188: {
 1189:   u_int32_t	self_magic;
 1190: 
 1191:   /* Validate magic number */
 1192:   bp = FsmCheckMagic(fp, bp);
 1193: 
 1194:   /* If not opened, do nothing */
 1195:   if (fp->state != ST_OPENED) {
 1196:     mbfree(bp);
 1197:     return;
 1198:   }
 1199: 
 1200:   /* Stick my magic number in there instead */
 1201:   self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
 1202:   bp = mbcopyback(bp, -(int)sizeof(self_magic), &self_magic, sizeof(self_magic));
 1203: 
 1204:   /* Send it back, preserving everything else */
 1205:   Log(LG_ECHO, ("[%s] %s: SendEchoRep #%d", Pref(fp), Fsm(fp), lhp->id));
 1206:   FsmOutputMbuf(fp, CODE_ECHOREP, lhp->id, bp);
 1207: }
 1208: 
 1209: /*
 1210:  * FsmRecvEchoRep()
 1211:  */
 1212: 
 1213: static void
 1214: FsmRecvEchoRep(Fsm fp, FsmHeader lhp, Mbuf bp)
 1215: {
 1216:   bp = FsmCheckMagic(fp, bp);
 1217:   mbfree(bp);
 1218: }
 1219: 
 1220: /*
 1221:  * FsmRecvDiscReq()
 1222:  */
 1223: 
 1224: static void
 1225: FsmRecvDiscReq(Fsm fp, FsmHeader lhp, Mbuf bp)
 1226: {
 1227:   bp = FsmCheckMagic(fp, bp);
 1228:   if (fp->type->RecvDiscReq)
 1229:     (*fp->type->RecvDiscReq)(fp, bp);
 1230:   mbfree(bp);
 1231: }
 1232: 
 1233: /*
 1234:  * FsmRecvIdent()
 1235:  */
 1236: 
 1237: static void
 1238: FsmRecvIdent(Fsm fp, FsmHeader lhp, Mbuf bp)
 1239: {
 1240:     bp = FsmCheckMagic(fp, bp);
 1241:     if (bp)
 1242:         ShowMesg(fp->log, Pref(fp), (char *) MBDATA(bp), MBLEN(bp));
 1243:     if (fp->type->RecvIdent)
 1244: 	(*fp->type->RecvIdent)(fp, bp);
 1245:     mbfree(bp);
 1246: }
 1247: 
 1248: /*
 1249:  * FsmRecvVendor()
 1250:  */
 1251: 
 1252: static void
 1253: FsmRecvVendor(Fsm fp, FsmHeader lhp, Mbuf bp)
 1254: {
 1255:     bp = FsmCheckMagic(fp, bp);
 1256:     if (fp->type->RecvVendor)
 1257: 	(*fp->type->RecvVendor)(fp, bp);
 1258:     mbfree(bp);
 1259: }
 1260: 
 1261: /*
 1262:  * FsmRecvTimeRemain()
 1263:  */
 1264: 
 1265: static void
 1266: FsmRecvTimeRemain(Fsm fp, FsmHeader lhp, Mbuf bp)
 1267: {
 1268:     bp = FsmCheckMagic(fp, bp);
 1269:     if (bp) {
 1270: 	u_int32_t	remain = 0;
 1271: 	mbcopy(bp, 0, &remain, sizeof(remain));
 1272: 	remain = ntohl(remain);
 1273: 	Log(fp->log, ("[%s]   %u seconds remain", Pref(fp), remain));
 1274:     }
 1275:     if (fp->type->RecvTimeRemain)
 1276: 	(*fp->type->RecvTimeRemain)(fp, bp);
 1277:     mbfree(bp);
 1278: }
 1279: 
 1280: /*
 1281:  * FsmRecvResetReq()
 1282:  */
 1283: 
 1284: static void
 1285: FsmRecvResetReq(Fsm fp, FsmHeader lhp, Mbuf bp)
 1286: {
 1287:   if (fp->type->RecvResetReq)
 1288:     (*fp->type->RecvResetReq)(fp, lhp->id, bp);
 1289:   mbfree(bp);
 1290: }
 1291: 
 1292: /*
 1293:  * FsmRecvResetAck()
 1294:  */
 1295: 
 1296: static void
 1297: FsmRecvResetAck(Fsm fp, FsmHeader lhp, Mbuf bp)
 1298: {
 1299:   if (fp->type->RecvResetAck)
 1300:     (*fp->type->RecvResetAck)(fp, lhp->id, bp);
 1301:   mbfree(bp);
 1302: }
 1303: 
 1304: /*
 1305:  * FsmLayerUp()
 1306:  */
 1307: 
 1308: static void
 1309: FsmLayerUp(Fsm fp)
 1310: {
 1311:   Log(fp->log2, ("[%s] %s: LayerUp", Pref(fp), Fsm(fp)));
 1312:   if (fp->type->LayerUp)
 1313:     (*fp->type->LayerUp)(fp);
 1314: }
 1315: 
 1316: /*
 1317:  * FsmLayerDown()
 1318:  */
 1319: 
 1320: static void
 1321: FsmLayerDown(Fsm fp)
 1322: {
 1323:   Log(fp->log2, ("[%s] %s: LayerDown", Pref(fp), Fsm(fp)));
 1324:   if (fp->type->LayerDown)
 1325:     (*fp->type->LayerDown)(fp);
 1326: }
 1327: 
 1328: /*
 1329:  * FsmLayerStart()
 1330:  */
 1331: 
 1332: static void
 1333: FsmLayerStart(Fsm fp)
 1334: {
 1335:   Log(fp->log2, ("[%s] %s: LayerStart", Pref(fp), Fsm(fp)));
 1336:   if (fp->type->LayerStart)
 1337:     (*fp->type->LayerStart)(fp);
 1338: }
 1339: 
 1340: /*
 1341:  * FsmLayerFinish()
 1342:  */
 1343: 
 1344: static void
 1345: FsmLayerFinish(Fsm fp)
 1346: {
 1347:   Log(fp->log2, ("[%s] %s: LayerFinish", Pref(fp), Fsm(fp)));
 1348:   if (fp->type->LayerFinish)
 1349:     (*fp->type->LayerFinish)(fp);
 1350: }
 1351: 
 1352: /*
 1353:  * FsmCheckMagic()
 1354:  */
 1355: 
 1356: static Mbuf
 1357: FsmCheckMagic(Fsm fp, Mbuf bp)
 1358: {
 1359:   u_int32_t	peer_magic;
 1360:   u_int32_t	peer_magic_ought;
 1361: 
 1362:   /* Read magic number */
 1363:   bp = mbread(bp, &peer_magic, sizeof(peer_magic));
 1364:   peer_magic = ntohl(peer_magic);
 1365: 
 1366:   /* What should magic number be? */
 1367:   if (PROT_LINK_LAYER(fp->type->proto))
 1368:     peer_magic_ought = ((Link)(fp->arg))->lcp.peer_magic;
 1369:   else
 1370:     peer_magic_ought = 0;
 1371: 
 1372:   /* Verify */
 1373:   if (fp->conf.check_magic && peer_magic != 0
 1374:      && peer_magic != peer_magic_ought) {
 1375:     Log(fp->log, ("[%s] %s: magic number is wrong: 0x%08x != 0x%08x",
 1376:       Pref(fp), Fsm(fp), peer_magic, peer_magic_ought));
 1377:     FsmFailure(fp, FAIL_RECD_BADMAGIC);
 1378:   }
 1379:   return(bp);
 1380: }
 1381: 
 1382: /*
 1383:  * FsmEchoTimeout()
 1384:  */
 1385: 
 1386: static void
 1387: FsmEchoTimeout(void *arg)
 1388: {
 1389:     Fsm			const fp = (Fsm) arg;
 1390:     Bund		b;
 1391:     Link		l;
 1392:     struct ng_ppp_link_stat	oldStats;
 1393: 
 1394:     if (fp->type->link_layer) {
 1395: 	l = (Link)fp->arg;
 1396: 	b = l->bund;
 1397:     } else {
 1398: 	b = (Bund)fp->arg;
 1399: 	l = NULL;
 1400:     }
 1401:     
 1402:     if (!b) {
 1403: 	/* We can't get link stat without bundle present */
 1404: 	return;
 1405:     }
 1406: 
 1407:     /* See if there was any traffic since last time */
 1408:     oldStats = fp->idleStats;
 1409:     NgFuncGetStats(b, l ?
 1410: 	l->bundleIndex : NG_PPP_BUNDLE_LINKNUM, &fp->idleStats);
 1411:     if (fp->idleStats.recvFrames > oldStats.recvFrames)
 1412: 	fp->quietCount = 0;
 1413:     else
 1414: 	fp->quietCount++;
 1415: 
 1416:     /* See if peer hasn't responded for too many requests */
 1417:     switch (fp->quietCount) {
 1418: 
 1419:     /* Peer failed to reply to previous echo request */
 1420:     default:
 1421:         Log(LG_ECHO|fp->log,
 1422: 	    ("[%s] %s: no reply to %d echo request(s)",
 1423: 	    Pref(fp), Fsm(fp), fp->quietCount - 1));
 1424: 
 1425:         /* Has peer failed to reply for maximum allowable interval? */
 1426:         if (fp->quietCount * fp->conf.echo_int >= fp->conf.echo_max) {
 1427: 	    TimerStop(&fp->echoTimer);
 1428: 	    FsmFailure(fp, FAIL_ECHO_TIMEOUT);
 1429: 	    break;
 1430:         }
 1431:         /* fall through */
 1432:     case 1:	/* one interval of silence elapsed; send first echo request */
 1433:         FsmSendEchoReq(fp, NULL);
 1434:         /* fall through */
 1435:     case 0:
 1436:         break;
 1437:     }
 1438: }
 1439: 
 1440: /*
 1441:  * FsmInput()
 1442:  *
 1443:  * Deal with an incoming packet for FSM pointed to by "fp"
 1444:  */
 1445: 
 1446: void
 1447: FsmInput(Fsm fp, Mbuf bp)
 1448: {
 1449:     int			log, recd_len, length;
 1450:     struct fsmheader	hdr;
 1451: 
 1452:     /* Check for runt frames; discard them */
 1453:     if ((recd_len = MBLEN(bp)) < sizeof(hdr)) {
 1454: 	Log(fp->log, ("[%s] %s: runt packet: %d bytes", Pref(fp), Fsm(fp), recd_len));
 1455: 	mbfree(bp);
 1456: 	return;
 1457:     }
 1458: 
 1459:     /* Read in the header */
 1460:     bp = mbread(bp, &hdr, sizeof(hdr));
 1461:     length = ntohs(hdr.length);
 1462: 
 1463:     /* Make sure length is sensible; discard otherwise */
 1464:     if (length < sizeof(hdr) || length > recd_len) {
 1465: 	Log(fp->log, ("[%s] %s: bad length: says %d, rec'd %d",
 1466:     	    Pref(fp), Fsm(fp), length, recd_len));
 1467: 	mbfree(bp);
 1468: 	return;
 1469:     }
 1470: 
 1471:     /* Truncate off any padding bytes */
 1472:     if (length < recd_len)
 1473: 	bp = mbtrunc(bp, length - sizeof(hdr));
 1474: 
 1475:     /* Check for a valid code byte -- if not, send code-reject */
 1476:     if ((hdr.code >= NUM_FSM_CODES) ||
 1477: 	    (((1 << hdr.code) & fp->type->known_codes) == 0)) {	/* RUC */
 1478: 	Log(fp->log, ("[%s] %s: unknown code %d", Pref(fp), Fsm(fp), hdr.code));
 1479: 	FsmOutputMbuf(fp, CODE_CODEREJ, fp->rejid++, bp);
 1480: 	return;
 1481:     }
 1482: 
 1483:     /* Log it */
 1484:     if (hdr.code == CODE_ECHOREQ || hdr.code == CODE_ECHOREP)
 1485: 	log = LG_ECHO;
 1486:     else if (hdr.code == CODE_RESETREQ || hdr.code == CODE_RESETACK)
 1487: 	log = fp->log2;
 1488:     else
 1489: 	log = fp->log;
 1490:     Log(log, ("[%s] %s: rec'd %s #%d (%s)",
 1491: 	Pref(fp), Fsm(fp), FsmCodeName(hdr.code), (int) hdr.id,
 1492: 	FsmStateName(fp->state)));
 1493: 
 1494:     /* Do whatever */
 1495:     (*FsmCodes[hdr.code].action)(fp, &hdr, bp);
 1496: }
 1497: 
 1498: /*
 1499:  * FsmConfValue()
 1500:  *
 1501:  * Write in a configuration item with "len" bytes of information.
 1502:  * Special cases: length -2 or -4 means convert to network byte order.
 1503:  */
 1504: 
 1505: u_char *
 1506: FsmConfValue(u_char *cp, int type, int len, const void *data)
 1507: {
 1508:   u_char	*bytes = (u_char *) data;
 1509:   u_int16_t	sv;
 1510:   u_int32_t	lv;
 1511: 
 1512:   /* Special cases */
 1513:   switch (len) {
 1514:     case -2:
 1515:       len = 2;
 1516:       sv = htons(*((u_int16_t *) data));
 1517:       bytes = (u_char *) &sv;
 1518:       break;
 1519:     case -4:
 1520:       len = 4;
 1521:       lv = htonl(*((u_int32_t *) data));
 1522:       bytes = (u_char *) &lv;
 1523:       break;
 1524:     default:
 1525:       break;
 1526:   }
 1527: 
 1528:   /* Add header and data */
 1529:   *cp++ = type;
 1530:   *cp++ = len + 2;
 1531:   while (len-- > 0)
 1532:     *cp++ = *bytes++;
 1533: 
 1534:   /* Done */
 1535:   return(cp);
 1536: }
 1537: 
 1538: /*
 1539:  * FsmExtractOptions()
 1540:  *
 1541:  * Extract options from a config packet
 1542:  */
 1543: 
 1544: static int
 1545: FsmExtractOptions(Fsm fp, u_char *data, int dlen, FsmOption opts, int max)
 1546: {
 1547:   int	num;
 1548: 
 1549:   for (num = 0; dlen >= 2 && num < max; num++) {
 1550:     FsmOption	const opt = &opts[num];
 1551: 
 1552:     opt->type = data[0];
 1553:     opt->len = data[1];
 1554:     opt->data = &data[2];
 1555:     if (opt->len < 2 || opt->len > dlen)
 1556:       break;
 1557:     data += opt->len;
 1558:     dlen -= opt->len;
 1559:   }
 1560:   if (dlen != 0)
 1561:     LogDumpBuf(LG_ERR, data, dlen,
 1562:       "[%s] %s: %d extra garbage bytes in config packet", Pref(fp), Fsm(fp), dlen);
 1563:   return(num);
 1564: }
 1565: 
 1566: /*
 1567:  * FsmFindOption()
 1568:  */
 1569: 
 1570: FsmOptInfo
 1571: FsmFindOptInfo(FsmOptInfo list, u_char type)
 1572: {
 1573:   for (; list->name; list++)
 1574:     if (list->type == type)
 1575:       return(list);
 1576:   return(NULL);
 1577: }
 1578: 
 1579: /*
 1580:  * FsmDecodeBuffer()
 1581:  */
 1582: 
 1583: static void
 1584: FsmDecodeBuffer(Fsm fp, u_char *buf, int size, int mode)
 1585: {
 1586:   struct fsmoption	opts[FSM_MAX_OPTS];
 1587:   int			num;
 1588: 
 1589:   if (mode == MODE_REQ)
 1590:     gAckSize = gNakSize = gRejSize = 0;
 1591:   num = FsmExtractOptions(fp, buf, size, opts, FSM_MAX_OPTS);
 1592:   (*fp->type->DecodeConfig)(fp, opts, num, mode);
 1593: }
 1594: 
 1595: /*
 1596:  * FsmAck()
 1597:  */
 1598: 
 1599: void
 1600: FsmAck(Fsm fp, const struct fsmoption *opt)
 1601: {
 1602:   if (gAckSize + opt->len > sizeof(gAckBuf)) {
 1603:     Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "ack"));
 1604:     return;
 1605:   }
 1606:   memcpy(&gAckBuf[gAckSize], opt, 2);
 1607:   memcpy(&gAckBuf[gAckSize + 2], opt->data, opt->len - 2);
 1608:   gAckSize += opt->len;
 1609: }
 1610: 
 1611: /*
 1612:  * FsmNak()
 1613:  */
 1614: 
 1615: void
 1616: FsmNak(Fsm fp, const struct fsmoption *opt)
 1617: {
 1618:   if (gNakSize + opt->len > sizeof(gNakBuf)) {
 1619:     Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "nak"));
 1620:     return;
 1621:   }
 1622:   memcpy(&gNakBuf[gNakSize], opt, 2);
 1623:   memcpy(&gNakBuf[gNakSize + 2], opt->data, opt->len - 2);
 1624:   gNakSize += opt->len;
 1625: }
 1626: 
 1627: /*
 1628:  * FsmRej()
 1629:  */
 1630: 
 1631: void
 1632: FsmRej(Fsm fp, const struct fsmoption *opt)
 1633: {
 1634:   if (gRejSize + opt->len > sizeof(gRejBuf)) {
 1635:     Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "rej"));
 1636:     return;
 1637:   }
 1638:   memcpy(&gRejBuf[gRejSize], opt, 2);
 1639:   memcpy(&gRejBuf[gRejSize + 2], opt->data, opt->len - 2);
 1640:   gRejSize += opt->len;
 1641: }
 1642: 
 1643: /*
 1644:  * FsmCodeName()
 1645:  */
 1646: 
 1647: const char *
 1648: FsmCodeName(int code)
 1649: {
 1650:   if (code >= 0 && code < NUM_FSM_CODES)
 1651:     return (FsmCodes[code].name);
 1652:   return ("UNKNOWN");
 1653: }
 1654: 
 1655: /*
 1656:  * FsmStateName()
 1657:  */
 1658: 
 1659: const char *
 1660: FsmStateName(enum fsm_state state)
 1661: {
 1662:   switch (state) {
 1663:     case ST_INITIAL:	return "Initial";
 1664:     case ST_STARTING:	return "Starting";
 1665:     case ST_CLOSED:	return "Closed";
 1666:     case ST_STOPPED:	return "Stopped";
 1667:     case ST_CLOSING:	return "Closing";
 1668:     case ST_STOPPING:	return "Stopping";
 1669:     case ST_REQSENT:	return "Req-Sent";
 1670:     case ST_ACKRCVD:	return "Ack-Rcvd";
 1671:     case ST_ACKSENT:	return "Ack-Sent";
 1672:     case ST_OPENED:	return "Opened";
 1673:   }
 1674:   return "???";
 1675: }
 1676: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>