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

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: {
1.1.1.3 ! misho     844:   (void)lhp;
1.1       misho     845:   if (fp->type->link_layer) {
                    846:     RecordLinkUpDownReason(NULL, (Link)(fp->arg), 0, STR_PEER_DISC, NULL);
                    847:   }
                    848:   switch (fp->state) {
                    849:     case ST_INITIAL:
                    850:     case ST_STARTING:
                    851:       Log(fp->log, ("[%s] %s: Oops, RTR in %s", Pref(fp), Fsm(fp), FsmStateName(fp->state)));
                    852:       break;
                    853:     case ST_CLOSED:
                    854:     case ST_STOPPED:
                    855:     case ST_CLOSING:
                    856:     case ST_STOPPING:
                    857:     case ST_REQSENT:
                    858:       FsmSendTerminateAck(fp);
                    859:       break;
                    860:     case ST_ACKRCVD:
                    861:     case ST_ACKSENT:
                    862:       FsmNewState(fp, ST_REQSENT);
                    863:       FsmSendTerminateAck(fp);
                    864:       break;
                    865:     case ST_OPENED:
                    866:       FsmNewState(fp, ST_STOPPING);
                    867:       FsmSendTerminateAck(fp);
                    868:       FsmLayerDown(fp);
                    869:       FsmInitRestartCounter(fp, 0);    /* Zero restart counter */
                    870:       TimerStart(&fp->timer);          /* Start restart timer */
                    871:       if (fp->type->UnConfigure)
                    872:        (*fp->type->UnConfigure)(fp);
                    873:       break;
                    874:   }
                    875:   mbfree(bp);
                    876: }
                    877: 
                    878: /* RTA */
                    879: 
                    880: static void
                    881: FsmRecvTermAck(Fsm fp, FsmHeader lhp, Mbuf bp)
                    882: {
1.1.1.3 ! misho     883:   (void)lhp;
1.1       misho     884:   switch (fp->state) {
                    885:     case ST_CLOSING:
                    886:       FsmNewState(fp, ST_CLOSED);
                    887:       FsmLayerFinish(fp);
                    888:       break;
                    889:     case ST_STOPPING:
                    890:       FsmNewState(fp, ST_STOPPED);
                    891:       FsmLayerFinish(fp);
                    892:       break;
                    893:     case ST_ACKRCVD:
                    894:       FsmNewState(fp, ST_REQSENT);
                    895:       break;
                    896:     case ST_OPENED:
                    897:       FsmNewState(fp, ST_REQSENT);
                    898:       FsmLayerDown(fp);
                    899:       FsmSendConfigReq(fp);
                    900:       break;
                    901:     default:
                    902:       break;
                    903:   }
                    904:   mbfree(bp);
                    905: }
                    906: 
                    907: /*
                    908:  * FsmRecvCodeRej()
                    909:  *
                    910:  * By default, this is fatal for most codes
                    911:  */
                    912: 
                    913: static void
                    914: FsmRecvCodeRej(Fsm fp, FsmHeader lhp, Mbuf bp)
                    915: {
                    916:   u_char       code = 0;
                    917:   int          fatal;
                    918: 
1.1.1.3 ! misho     919:   (void)lhp;
1.1       misho     920:   /* Get code and log it */
                    921:   bp = mbread(bp, &code, sizeof(code));
                    922:   Log(fp->log, ("[%s] %s: code %s was rejected", Pref(fp), Fsm(fp), FsmCodeName(code)));
                    923: 
                    924:   /* Determine fatalness */
                    925:   if (fp->type->RecvCodeRej)
                    926:     fatal = (*fp->type->RecvCodeRej)(fp, code, bp);
                    927:   else {
                    928:     switch (code) {
                    929:       case CODE_CONFIGREQ:
                    930:       case CODE_CONFIGACK:
                    931:       case CODE_CONFIGNAK:
                    932:       case CODE_CONFIGREJ:
                    933:       case CODE_TERMREQ:
                    934:       case CODE_TERMACK:
                    935:       case CODE_CODEREJ:
                    936:       case CODE_PROTOREJ:
                    937:       case CODE_ECHOREQ:
                    938:       case CODE_ECHOREP:
                    939:       case CODE_RESETREQ:
                    940:       case CODE_RESETACK:
                    941:        fatal = TRUE;
                    942:        break;
                    943:       case CODE_VENDOR:
                    944:       case CODE_DISCREQ:
                    945:       case CODE_IDENT:
                    946:       case CODE_TIMEREM:
                    947:       default:         /* if we don't know it, that makes two of us */
                    948:        fatal = FALSE;
                    949:        break;
                    950:     }
                    951:   }
                    952: 
                    953:   /* Possibly shut down as a result */
                    954:   if (fatal)
                    955:     FsmFailure(fp, FAIL_RECD_CODEREJ);         /* RXJ- */
                    956:   else
                    957:     FsmRecvRxjPlus(fp);
                    958:   mbfree(bp);
                    959: }
                    960: 
                    961: /*
                    962:  * FsmRecvProtoRej()
                    963:  *
                    964:  * By default, this is non-fatal
                    965:  */
                    966: 
                    967: static void
                    968: FsmRecvProtoRej(Fsm fp, FsmHeader lhp, Mbuf bp)
                    969: {
                    970:   u_short      proto = 0;
                    971:   int          fatal = FALSE;
                    972: 
1.1.1.3 ! misho     973:   (void)lhp;
1.1       misho     974:   bp = mbread(bp, &proto, sizeof(proto));
                    975:   proto = ntohs(proto);
                    976:   Log(fp->log, ("[%s] %s: protocol %s was rejected", Pref(fp), Fsm(fp), ProtoName(proto)));
                    977:   if (fp->state == ST_OPENED && fp->type->RecvProtoRej)
                    978:     fatal = (*fp->type->RecvProtoRej)(fp, proto, bp);
                    979:   if (fatal)
                    980:     FsmFailure(fp, FAIL_RECD_PROTREJ);         /* RXJ- */
                    981:   else
                    982:     FsmRecvRxjPlus(fp);
                    983:   mbfree(bp);
                    984: }
                    985: 
                    986: /*
                    987:  * FsmRecvRxjPlus()
                    988:  */
                    989: 
                    990: static void
                    991: FsmRecvRxjPlus(Fsm fp)                         /* RXJ+ */
                    992: {
                    993:   switch (fp->state) {
                    994:     case ST_ACKRCVD:
                    995:       FsmNewState(fp, ST_REQSENT);
                    996:       break;
                    997:     default:
                    998:       break;
                    999:   }
                   1000: }
                   1001: 
                   1002: /*
                   1003:  * FsmFailure()
                   1004:  *
                   1005:  * Call this at any point if something fatal happens that is inherent
                   1006:  * to the FSM itself, like a RXJ- event or negotiation failed to converge.
                   1007:  * The action taken is like the RXJ- event.
                   1008:  */
                   1009: 
                   1010: void
                   1011: FsmFailure(Fsm fp, enum fsmfail reason)
                   1012: {
                   1013:   Log(fp->log, ("[%s] %s: %s", Pref(fp), Fsm(fp), FsmFailureStr(reason)));
                   1014: 
                   1015:   /* Let layer do any special handling of error code */
                   1016:   if (fp->type->Failure)
                   1017:     (*fp->type->Failure)(fp, reason);
                   1018: 
                   1019:   /* Shut this state machine down */
                   1020:   switch (fp->state) {
                   1021:     case ST_CLOSING:
                   1022:       FsmNewState(fp, ST_CLOSED);
                   1023:       /* fall through */
                   1024:     case ST_CLOSED:
                   1025:       FsmLayerFinish(fp);
                   1026:       break;
                   1027:     case ST_STOPPING:
                   1028:       FsmNewState(fp, ST_STOPPED);
                   1029:       FsmLayerFinish(fp);
                   1030:       break;
                   1031:     case ST_ACKRCVD:
                   1032:     case ST_ACKSENT:
                   1033:     case ST_REQSENT:
                   1034:       FsmNewState(fp, ST_STOPPED);
                   1035:       if (!fp->conf.passive)
                   1036:        FsmLayerFinish(fp);
                   1037:       if (fp->type->UnConfigure)
                   1038:        (*fp->type->UnConfigure)(fp);
                   1039:       break;
                   1040: 
                   1041:     /*
                   1042:      * In the opened state, the peer FSM has somehow died or did something
                   1043:      * horribly wrong to us. So the common sense action in this case is to 
                   1044:      * bring the whole link down, rather than restarting just the FSM.
                   1045:      * We do this by telling the lower layer to restart using tlf and tls
                   1046:      * while also pretending that we got a DOWN event.
                   1047:      */
                   1048:     case ST_OPENED:
                   1049:       FsmNewState(fp, ST_STOPPING);
                   1050:       FsmInitRestartCounter(fp, fp->conf.maxterminate);
                   1051:       FsmSendTerminateReq(fp);
                   1052:       FsmLayerDown(fp);
                   1053:       if (fp->type->UnConfigure)
                   1054:        (*fp->type->UnConfigure)(fp);
                   1055:       break;
                   1056: 
                   1057:     /*
                   1058:      * In the STOPPED state, then most likely the negotiation timed out
                   1059:      * or didn't converge. Just wait for the DOWN event from the previously
                   1060:      * issued tlf action.
                   1061:      */
                   1062:     case ST_STOPPED:
                   1063:       if (!fp->conf.passive)
                   1064:        FsmLayerFinish(fp);
                   1065:       break;
                   1066:     default:
                   1067:       break;
                   1068:   }
                   1069: }
                   1070: 
                   1071: /*
                   1072:  * FsmFailureStr()
                   1073:  */
                   1074: 
                   1075: const char *
                   1076: FsmFailureStr(enum fsmfail reason)
                   1077: {
                   1078:   const char   *string = NULL;
                   1079: 
                   1080:   switch (reason) {
                   1081:     case FAIL_NEGOT_FAILURE:
                   1082:       string = STR_FAIL_NEGOT_FAILURE;
                   1083:       break;
                   1084:     case FAIL_RECD_BADMAGIC:
                   1085:       string = STR_FAIL_RECD_BADMAGIC;
                   1086:       break;
                   1087:     case FAIL_RECD_CODEREJ:
                   1088:       string = STR_FAIL_RECD_CODEREJ;
                   1089:       break;
                   1090:     case FAIL_RECD_PROTREJ:
                   1091:       string = STR_FAIL_RECD_PROTREJ;
                   1092:       break;
                   1093:     case FAIL_WAS_PROTREJ:
                   1094:       string = STR_FAIL_WAS_PROTREJ;
                   1095:       break;
                   1096:     case FAIL_ECHO_TIMEOUT:
                   1097:       string = STR_FAIL_ECHO_TIMEOUT;
                   1098:       break;
                   1099:     case FAIL_CANT_ENCRYPT:
                   1100:       string = STR_FAIL_CANT_ENCRYPT;
                   1101:       break;
                   1102:     default:
                   1103:       assert(0);
                   1104:   }
                   1105:   return(string);
                   1106: }
                   1107: 
                   1108: /*
                   1109:  * FsmSendEchoReq()
                   1110:  *
                   1111:  * Send an echo request containing the supplied payload data.
                   1112:  * Consumes the mbuf.
                   1113:  */
                   1114: 
                   1115: void
                   1116: FsmSendEchoReq(Fsm fp, Mbuf payload)
                   1117: {
                   1118:   u_int32_t    const self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
                   1119:   Mbuf         bp;
                   1120: 
                   1121:   if (fp->state != ST_OPENED)
                   1122:     return;
                   1123: 
                   1124:   /* Prepend my magic number */
                   1125:   bp = mbcopyback(payload, -(int)sizeof(self_magic), &self_magic, sizeof(self_magic));
                   1126: 
                   1127:   /* Send it */
                   1128:   Log(LG_ECHO, ("[%s] %s: SendEchoReq #%d", Pref(fp), Fsm(fp), fp->echoid));
                   1129:   FsmOutputMbuf(fp, CODE_ECHOREQ, fp->echoid++, bp);
                   1130: }
                   1131: 
                   1132: /*
                   1133:  * FsmSendIdent()
                   1134:  *
                   1135:  * Send an LCP ident packet.
                   1136:  */
                   1137: 
                   1138: void
                   1139: FsmSendIdent(Fsm fp, const char *ident)
                   1140: {
                   1141:   u_int32_t    self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
                   1142:   const int    len = strlen(ident) + 1;        /* include NUL to be nice */
                   1143:   Mbuf         bp;
                   1144: 
                   1145:   /* Leave magic zero unless fully opened, as IDENT can be sent anytime */
                   1146:   if (fp->state != ST_OPENED)
                   1147:     self_magic = 0;
                   1148: 
                   1149:   /* Prepend my magic number */
                   1150:   bp = mbcopyback(NULL, 0, (u_char *) &self_magic, sizeof(self_magic));
                   1151:   bp = mbcopyback(bp, sizeof(self_magic), ident, len);
                   1152: 
                   1153:   /* Send it */
1.1.1.2   misho    1154:   Log(fp->log2, ("[%s] %s: SendIdent #%d", Pref(fp), Fsm(fp), fp->echoid));
                   1155:   ShowMesg(fp->log2, Pref(fp), ident, len);
1.1       misho    1156:   FsmOutputMbuf(fp, CODE_IDENT, fp->echoid++, bp);
                   1157: }
                   1158: 
                   1159: /*
                   1160:  * FsmSendTimeRemaining()
                   1161:  *
                   1162:  * Send an LCP Time-Remaining packet.
                   1163:  */
                   1164: 
                   1165: void
                   1166: FsmSendTimeRemaining(Fsm fp, u_int seconds)
                   1167: {
                   1168:   u_int32_t    self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
                   1169:   u_int32_t    data = htonl(seconds);
                   1170:   Mbuf         bp;
                   1171: 
                   1172:   /* Leave magic zero unless fully opened, as IDENT can be sent anytime */
                   1173:   if (fp->state != ST_OPENED)
                   1174:     self_magic = 0;
                   1175: 
                   1176:   /* Prepend my magic number */
                   1177:   bp = mbcopyback(NULL, 0, (u_char *) &self_magic, sizeof(self_magic));
                   1178:   bp = mbcopyback(bp, sizeof(self_magic), &data, 4);
                   1179: 
                   1180:   /* Send it */
1.1.1.2   misho    1181:   Log(fp->log2, ("[%s] %s: SendTimeRemaining #%d", Pref(fp), Fsm(fp), fp->echoid));
                   1182:   Log(fp->log2, ("[%s]   %u seconds remain", Pref(fp), seconds));
1.1       misho    1183:   FsmOutputMbuf(fp, CODE_TIMEREM, fp->echoid++, bp);
                   1184: }
                   1185: 
                   1186: /*
                   1187:  * FsmRecvEchoReq()
                   1188:  */
                   1189: 
                   1190: static void
                   1191: FsmRecvEchoReq(Fsm fp, FsmHeader lhp, Mbuf bp)
                   1192: {
                   1193:   u_int32_t    self_magic;
                   1194: 
                   1195:   /* Validate magic number */
                   1196:   bp = FsmCheckMagic(fp, bp);
                   1197: 
                   1198:   /* If not opened, do nothing */
                   1199:   if (fp->state != ST_OPENED) {
                   1200:     mbfree(bp);
                   1201:     return;
                   1202:   }
                   1203: 
                   1204:   /* Stick my magic number in there instead */
                   1205:   self_magic = htonl(((Link)(fp->arg))->lcp.want_magic);
                   1206:   bp = mbcopyback(bp, -(int)sizeof(self_magic), &self_magic, sizeof(self_magic));
                   1207: 
                   1208:   /* Send it back, preserving everything else */
                   1209:   Log(LG_ECHO, ("[%s] %s: SendEchoRep #%d", Pref(fp), Fsm(fp), lhp->id));
                   1210:   FsmOutputMbuf(fp, CODE_ECHOREP, lhp->id, bp);
                   1211: }
                   1212: 
                   1213: /*
                   1214:  * FsmRecvEchoRep()
                   1215:  */
                   1216: 
                   1217: static void
                   1218: FsmRecvEchoRep(Fsm fp, FsmHeader lhp, Mbuf bp)
                   1219: {
1.1.1.3 ! misho    1220:   (void)lhp;
1.1       misho    1221:   bp = FsmCheckMagic(fp, bp);
                   1222:   mbfree(bp);
                   1223: }
                   1224: 
                   1225: /*
                   1226:  * FsmRecvDiscReq()
                   1227:  */
                   1228: 
                   1229: static void
                   1230: FsmRecvDiscReq(Fsm fp, FsmHeader lhp, Mbuf bp)
                   1231: {
1.1.1.3 ! misho    1232:   (void)lhp;
1.1       misho    1233:   bp = FsmCheckMagic(fp, bp);
                   1234:   if (fp->type->RecvDiscReq)
                   1235:     (*fp->type->RecvDiscReq)(fp, bp);
                   1236:   mbfree(bp);
                   1237: }
                   1238: 
                   1239: /*
                   1240:  * FsmRecvIdent()
                   1241:  */
                   1242: 
                   1243: static void
                   1244: FsmRecvIdent(Fsm fp, FsmHeader lhp, Mbuf bp)
                   1245: {
1.1.1.3 ! misho    1246:     (void)lhp;
1.1       misho    1247:     bp = FsmCheckMagic(fp, bp);
                   1248:     if (bp)
                   1249:         ShowMesg(fp->log, Pref(fp), (char *) MBDATA(bp), MBLEN(bp));
                   1250:     if (fp->type->RecvIdent)
                   1251:        (*fp->type->RecvIdent)(fp, bp);
                   1252:     mbfree(bp);
                   1253: }
                   1254: 
                   1255: /*
                   1256:  * FsmRecvVendor()
                   1257:  */
                   1258: 
                   1259: static void
                   1260: FsmRecvVendor(Fsm fp, FsmHeader lhp, Mbuf bp)
                   1261: {
1.1.1.3 ! misho    1262:     (void)lhp;
1.1       misho    1263:     bp = FsmCheckMagic(fp, bp);
                   1264:     if (fp->type->RecvVendor)
                   1265:        (*fp->type->RecvVendor)(fp, bp);
                   1266:     mbfree(bp);
                   1267: }
                   1268: 
                   1269: /*
                   1270:  * FsmRecvTimeRemain()
                   1271:  */
                   1272: 
                   1273: static void
                   1274: FsmRecvTimeRemain(Fsm fp, FsmHeader lhp, Mbuf bp)
                   1275: {
1.1.1.3 ! misho    1276:     (void)lhp;
1.1       misho    1277:     bp = FsmCheckMagic(fp, bp);
                   1278:     if (bp) {
                   1279:        u_int32_t       remain = 0;
                   1280:        mbcopy(bp, 0, &remain, sizeof(remain));
                   1281:        remain = ntohl(remain);
                   1282:        Log(fp->log, ("[%s]   %u seconds remain", Pref(fp), remain));
                   1283:     }
                   1284:     if (fp->type->RecvTimeRemain)
                   1285:        (*fp->type->RecvTimeRemain)(fp, bp);
                   1286:     mbfree(bp);
                   1287: }
                   1288: 
                   1289: /*
                   1290:  * FsmRecvResetReq()
                   1291:  */
                   1292: 
                   1293: static void
                   1294: FsmRecvResetReq(Fsm fp, FsmHeader lhp, Mbuf bp)
                   1295: {
                   1296:   if (fp->type->RecvResetReq)
                   1297:     (*fp->type->RecvResetReq)(fp, lhp->id, bp);
                   1298:   mbfree(bp);
                   1299: }
                   1300: 
                   1301: /*
                   1302:  * FsmRecvResetAck()
                   1303:  */
                   1304: 
                   1305: static void
                   1306: FsmRecvResetAck(Fsm fp, FsmHeader lhp, Mbuf bp)
                   1307: {
                   1308:   if (fp->type->RecvResetAck)
                   1309:     (*fp->type->RecvResetAck)(fp, lhp->id, bp);
                   1310:   mbfree(bp);
                   1311: }
                   1312: 
                   1313: /*
                   1314:  * FsmLayerUp()
                   1315:  */
                   1316: 
                   1317: static void
                   1318: FsmLayerUp(Fsm fp)
                   1319: {
                   1320:   Log(fp->log2, ("[%s] %s: LayerUp", Pref(fp), Fsm(fp)));
                   1321:   if (fp->type->LayerUp)
                   1322:     (*fp->type->LayerUp)(fp);
                   1323: }
                   1324: 
                   1325: /*
                   1326:  * FsmLayerDown()
                   1327:  */
                   1328: 
                   1329: static void
                   1330: FsmLayerDown(Fsm fp)
                   1331: {
                   1332:   Log(fp->log2, ("[%s] %s: LayerDown", Pref(fp), Fsm(fp)));
                   1333:   if (fp->type->LayerDown)
                   1334:     (*fp->type->LayerDown)(fp);
                   1335: }
                   1336: 
                   1337: /*
                   1338:  * FsmLayerStart()
                   1339:  */
                   1340: 
                   1341: static void
                   1342: FsmLayerStart(Fsm fp)
                   1343: {
                   1344:   Log(fp->log2, ("[%s] %s: LayerStart", Pref(fp), Fsm(fp)));
                   1345:   if (fp->type->LayerStart)
                   1346:     (*fp->type->LayerStart)(fp);
                   1347: }
                   1348: 
                   1349: /*
                   1350:  * FsmLayerFinish()
                   1351:  */
                   1352: 
                   1353: static void
                   1354: FsmLayerFinish(Fsm fp)
                   1355: {
                   1356:   Log(fp->log2, ("[%s] %s: LayerFinish", Pref(fp), Fsm(fp)));
                   1357:   if (fp->type->LayerFinish)
                   1358:     (*fp->type->LayerFinish)(fp);
                   1359: }
                   1360: 
                   1361: /*
                   1362:  * FsmCheckMagic()
                   1363:  */
                   1364: 
                   1365: static Mbuf
                   1366: FsmCheckMagic(Fsm fp, Mbuf bp)
                   1367: {
                   1368:   u_int32_t    peer_magic;
                   1369:   u_int32_t    peer_magic_ought;
                   1370: 
                   1371:   /* Read magic number */
                   1372:   bp = mbread(bp, &peer_magic, sizeof(peer_magic));
                   1373:   peer_magic = ntohl(peer_magic);
                   1374: 
                   1375:   /* What should magic number be? */
                   1376:   if (PROT_LINK_LAYER(fp->type->proto))
                   1377:     peer_magic_ought = ((Link)(fp->arg))->lcp.peer_magic;
                   1378:   else
                   1379:     peer_magic_ought = 0;
                   1380: 
                   1381:   /* Verify */
                   1382:   if (fp->conf.check_magic && peer_magic != 0
                   1383:      && peer_magic != peer_magic_ought) {
                   1384:     Log(fp->log, ("[%s] %s: magic number is wrong: 0x%08x != 0x%08x",
                   1385:       Pref(fp), Fsm(fp), peer_magic, peer_magic_ought));
                   1386:     FsmFailure(fp, FAIL_RECD_BADMAGIC);
                   1387:   }
                   1388:   return(bp);
                   1389: }
                   1390: 
                   1391: /*
                   1392:  * FsmEchoTimeout()
                   1393:  */
                   1394: 
                   1395: static void
                   1396: FsmEchoTimeout(void *arg)
                   1397: {
                   1398:     Fsm                        const fp = (Fsm) arg;
                   1399:     Bund               b;
                   1400:     Link               l;
1.1.1.3 ! misho    1401: #ifndef NG_PPP_STATS64
1.1       misho    1402:     struct ng_ppp_link_stat    oldStats;
1.1.1.3 ! misho    1403: #else
        !          1404:     struct ng_ppp_link_stat64  oldStats;
        !          1405: #endif
1.1       misho    1406: 
                   1407:     if (fp->type->link_layer) {
                   1408:        l = (Link)fp->arg;
                   1409:        b = l->bund;
                   1410:     } else {
                   1411:        b = (Bund)fp->arg;
                   1412:        l = NULL;
                   1413:     }
                   1414:     
                   1415:     if (!b) {
                   1416:        /* We can't get link stat without bundle present */
                   1417:        return;
                   1418:     }
                   1419: 
                   1420:     /* See if there was any traffic since last time */
                   1421:     oldStats = fp->idleStats;
1.1.1.3 ! misho    1422: #ifndef NG_PPP_STATS64
1.1       misho    1423:     NgFuncGetStats(b, l ?
                   1424:        l->bundleIndex : NG_PPP_BUNDLE_LINKNUM, &fp->idleStats);
1.1.1.3 ! misho    1425: #else
        !          1426:     NgFuncGetStats64(b, l ?
        !          1427:        l->bundleIndex : NG_PPP_BUNDLE_LINKNUM, &fp->idleStats);
        !          1428: #endif
1.1       misho    1429:     if (fp->idleStats.recvFrames > oldStats.recvFrames)
                   1430:        fp->quietCount = 0;
                   1431:     else
                   1432:        fp->quietCount++;
                   1433: 
                   1434:     /* See if peer hasn't responded for too many requests */
                   1435:     switch (fp->quietCount) {
                   1436: 
                   1437:     /* Peer failed to reply to previous echo request */
                   1438:     default:
                   1439:         Log(LG_ECHO|fp->log,
                   1440:            ("[%s] %s: no reply to %d echo request(s)",
                   1441:            Pref(fp), Fsm(fp), fp->quietCount - 1));
                   1442: 
                   1443:         /* Has peer failed to reply for maximum allowable interval? */
                   1444:         if (fp->quietCount * fp->conf.echo_int >= fp->conf.echo_max) {
                   1445:            TimerStop(&fp->echoTimer);
                   1446:            FsmFailure(fp, FAIL_ECHO_TIMEOUT);
                   1447:            break;
                   1448:         }
                   1449:         /* fall through */
                   1450:     case 1:    /* one interval of silence elapsed; send first echo request */
                   1451:         FsmSendEchoReq(fp, NULL);
                   1452:         /* fall through */
                   1453:     case 0:
                   1454:         break;
                   1455:     }
                   1456: }
                   1457: 
                   1458: /*
                   1459:  * FsmInput()
                   1460:  *
                   1461:  * Deal with an incoming packet for FSM pointed to by "fp"
                   1462:  */
                   1463: 
                   1464: void
                   1465: FsmInput(Fsm fp, Mbuf bp)
                   1466: {
1.1.1.3 ! misho    1467:     int                        log;
        !          1468:     unsigned           length, recd_len;
1.1       misho    1469:     struct fsmheader   hdr;
                   1470: 
                   1471:     /* Check for runt frames; discard them */
                   1472:     if ((recd_len = MBLEN(bp)) < sizeof(hdr)) {
1.1.1.3 ! misho    1473:        Log(fp->log, ("[%s] %s: runt packet: %u bytes", Pref(fp), Fsm(fp), recd_len));
1.1       misho    1474:        mbfree(bp);
                   1475:        return;
                   1476:     }
                   1477: 
                   1478:     /* Read in the header */
                   1479:     bp = mbread(bp, &hdr, sizeof(hdr));
                   1480:     length = ntohs(hdr.length);
                   1481: 
                   1482:     /* Make sure length is sensible; discard otherwise */
                   1483:     if (length < sizeof(hdr) || length > recd_len) {
1.1.1.3 ! misho    1484:        Log(fp->log, ("[%s] %s: bad length: says %u, rec'd %u",
1.1       misho    1485:            Pref(fp), Fsm(fp), length, recd_len));
                   1486:        mbfree(bp);
                   1487:        return;
                   1488:     }
                   1489: 
                   1490:     /* Truncate off any padding bytes */
                   1491:     if (length < recd_len)
                   1492:        bp = mbtrunc(bp, length - sizeof(hdr));
                   1493: 
                   1494:     /* Check for a valid code byte -- if not, send code-reject */
                   1495:     if ((hdr.code >= NUM_FSM_CODES) ||
                   1496:            (((1 << hdr.code) & fp->type->known_codes) == 0)) { /* RUC */
                   1497:        Log(fp->log, ("[%s] %s: unknown code %d", Pref(fp), Fsm(fp), hdr.code));
                   1498:        FsmOutputMbuf(fp, CODE_CODEREJ, fp->rejid++, bp);
                   1499:        return;
                   1500:     }
                   1501: 
                   1502:     /* Log it */
                   1503:     if (hdr.code == CODE_ECHOREQ || hdr.code == CODE_ECHOREP)
                   1504:        log = LG_ECHO;
                   1505:     else if (hdr.code == CODE_RESETREQ || hdr.code == CODE_RESETACK)
                   1506:        log = fp->log2;
                   1507:     else
                   1508:        log = fp->log;
                   1509:     Log(log, ("[%s] %s: rec'd %s #%d (%s)",
                   1510:        Pref(fp), Fsm(fp), FsmCodeName(hdr.code), (int) hdr.id,
                   1511:        FsmStateName(fp->state)));
                   1512: 
                   1513:     /* Do whatever */
                   1514:     (*FsmCodes[hdr.code].action)(fp, &hdr, bp);
                   1515: }
                   1516: 
                   1517: /*
                   1518:  * FsmConfValue()
                   1519:  *
                   1520:  * Write in a configuration item with "len" bytes of information.
                   1521:  * Special cases: length -2 or -4 means convert to network byte order.
                   1522:  */
                   1523: 
                   1524: u_char *
                   1525: FsmConfValue(u_char *cp, int type, int len, const void *data)
                   1526: {
1.1.1.3 ! misho    1527:   const u_char *bytes = (const u_char *) data;
1.1       misho    1528:   u_int16_t    sv;
                   1529:   u_int32_t    lv;
                   1530: 
                   1531:   /* Special cases */
                   1532:   switch (len) {
                   1533:     case -2:
                   1534:       len = 2;
1.1.1.3 ! misho    1535:       sv = htons(*((const u_int16_t *) data));
1.1       misho    1536:       bytes = (u_char *) &sv;
                   1537:       break;
                   1538:     case -4:
                   1539:       len = 4;
1.1.1.3 ! misho    1540:       lv = htonl(*((const u_int32_t *) data));
1.1       misho    1541:       bytes = (u_char *) &lv;
                   1542:       break;
                   1543:     default:
                   1544:       break;
                   1545:   }
                   1546: 
                   1547:   /* Add header and data */
                   1548:   *cp++ = type;
                   1549:   *cp++ = len + 2;
                   1550:   while (len-- > 0)
                   1551:     *cp++ = *bytes++;
                   1552: 
                   1553:   /* Done */
                   1554:   return(cp);
                   1555: }
                   1556: 
                   1557: /*
                   1558:  * FsmExtractOptions()
                   1559:  *
                   1560:  * Extract options from a config packet
                   1561:  */
                   1562: 
                   1563: static int
                   1564: FsmExtractOptions(Fsm fp, u_char *data, int dlen, FsmOption opts, int max)
                   1565: {
                   1566:   int  num;
                   1567: 
                   1568:   for (num = 0; dlen >= 2 && num < max; num++) {
                   1569:     FsmOption  const opt = &opts[num];
                   1570: 
                   1571:     opt->type = data[0];
                   1572:     opt->len = data[1];
                   1573:     opt->data = &data[2];
                   1574:     if (opt->len < 2 || opt->len > dlen)
                   1575:       break;
                   1576:     data += opt->len;
                   1577:     dlen -= opt->len;
                   1578:   }
                   1579:   if (dlen != 0)
                   1580:     LogDumpBuf(LG_ERR, data, dlen,
                   1581:       "[%s] %s: %d extra garbage bytes in config packet", Pref(fp), Fsm(fp), dlen);
                   1582:   return(num);
                   1583: }
                   1584: 
                   1585: /*
                   1586:  * FsmFindOption()
                   1587:  */
                   1588: 
                   1589: FsmOptInfo
                   1590: FsmFindOptInfo(FsmOptInfo list, u_char type)
                   1591: {
                   1592:   for (; list->name; list++)
                   1593:     if (list->type == type)
                   1594:       return(list);
                   1595:   return(NULL);
                   1596: }
                   1597: 
                   1598: /*
                   1599:  * FsmDecodeBuffer()
                   1600:  */
                   1601: 
                   1602: static void
                   1603: FsmDecodeBuffer(Fsm fp, u_char *buf, int size, int mode)
                   1604: {
                   1605:   struct fsmoption     opts[FSM_MAX_OPTS];
                   1606:   int                  num;
                   1607: 
                   1608:   if (mode == MODE_REQ)
                   1609:     gAckSize = gNakSize = gRejSize = 0;
                   1610:   num = FsmExtractOptions(fp, buf, size, opts, FSM_MAX_OPTS);
                   1611:   (*fp->type->DecodeConfig)(fp, opts, num, mode);
                   1612: }
                   1613: 
                   1614: /*
                   1615:  * FsmAck()
                   1616:  */
                   1617: 
                   1618: void
                   1619: FsmAck(Fsm fp, const struct fsmoption *opt)
                   1620: {
                   1621:   if (gAckSize + opt->len > sizeof(gAckBuf)) {
                   1622:     Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "ack"));
                   1623:     return;
                   1624:   }
                   1625:   memcpy(&gAckBuf[gAckSize], opt, 2);
                   1626:   memcpy(&gAckBuf[gAckSize + 2], opt->data, opt->len - 2);
                   1627:   gAckSize += opt->len;
                   1628: }
                   1629: 
                   1630: /*
                   1631:  * FsmNak()
                   1632:  */
                   1633: 
                   1634: void
                   1635: FsmNak(Fsm fp, const struct fsmoption *opt)
                   1636: {
                   1637:   if (gNakSize + opt->len > sizeof(gNakBuf)) {
                   1638:     Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "nak"));
                   1639:     return;
                   1640:   }
                   1641:   memcpy(&gNakBuf[gNakSize], opt, 2);
                   1642:   memcpy(&gNakBuf[gNakSize + 2], opt->data, opt->len - 2);
                   1643:   gNakSize += opt->len;
                   1644: }
                   1645: 
                   1646: /*
                   1647:  * FsmRej()
                   1648:  */
                   1649: 
                   1650: void
                   1651: FsmRej(Fsm fp, const struct fsmoption *opt)
                   1652: {
                   1653:   if (gRejSize + opt->len > sizeof(gRejBuf)) {
                   1654:     Log(LG_ERR, ("[%s] %s: %s buffer full", Pref(fp), Fsm(fp), "rej"));
                   1655:     return;
                   1656:   }
                   1657:   memcpy(&gRejBuf[gRejSize], opt, 2);
                   1658:   memcpy(&gRejBuf[gRejSize + 2], opt->data, opt->len - 2);
                   1659:   gRejSize += opt->len;
                   1660: }
                   1661: 
                   1662: /*
                   1663:  * FsmCodeName()
                   1664:  */
                   1665: 
                   1666: const char *
                   1667: FsmCodeName(int code)
                   1668: {
1.1.1.3 ! misho    1669:   if (code >= 0 && code < (int)NUM_FSM_CODES)
1.1       misho    1670:     return (FsmCodes[code].name);
                   1671:   return ("UNKNOWN");
                   1672: }
                   1673: 
                   1674: /*
                   1675:  * FsmStateName()
                   1676:  */
                   1677: 
                   1678: const char *
                   1679: FsmStateName(enum fsm_state state)
                   1680: {
                   1681:   switch (state) {
                   1682:     case ST_INITIAL:   return "Initial";
                   1683:     case ST_STARTING:  return "Starting";
                   1684:     case ST_CLOSED:    return "Closed";
                   1685:     case ST_STOPPED:   return "Stopped";
                   1686:     case ST_CLOSING:   return "Closing";
                   1687:     case ST_STOPPING:  return "Stopping";
                   1688:     case ST_REQSENT:   return "Req-Sent";
                   1689:     case ST_ACKRCVD:   return "Ack-Rcvd";
                   1690:     case ST_ACKSENT:   return "Ack-Sent";
                   1691:     case ST_OPENED:    return "Opened";
                   1692:   }
                   1693:   return "???";
                   1694: }
                   1695: 

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