Annotation of embedaddon/mpd/src/fsm.c, revision 1.1.1.1

1.1       misho       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(LG_FSM, ("[%s] %s: SendIdent #%d", Pref(fp), Fsm(fp), fp->echoid));
                   1151:   ShowMesg(LG_FSM, 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(LG_FSM, ("[%s] %s: SendTimeRemaining #%d", Pref(fp), Fsm(fp), fp->echoid));
                   1178:   Log(LG_FSM, ("[%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>