11ae349f5Scvs2svn /* 21ae349f5Scvs2svn * PPP Finite State Machine for LCP/IPCP 31ae349f5Scvs2svn * 41ae349f5Scvs2svn * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 51ae349f5Scvs2svn * 61ae349f5Scvs2svn * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 71ae349f5Scvs2svn * 81ae349f5Scvs2svn * Redistribution and use in source and binary forms are permitted 91ae349f5Scvs2svn * provided that the above copyright notice and this paragraph are 101ae349f5Scvs2svn * duplicated in all such forms and that any documentation, 111ae349f5Scvs2svn * advertising materials, and other materials related to such 121ae349f5Scvs2svn * distribution and use acknowledge that the software was developed 131ae349f5Scvs2svn * by the Internet Initiative Japan, Inc. The name of the 141ae349f5Scvs2svn * IIJ may not be used to endorse or promote products derived 151ae349f5Scvs2svn * from this software without specific prior written permission. 161ae349f5Scvs2svn * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 171ae349f5Scvs2svn * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 181ae349f5Scvs2svn * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 191ae349f5Scvs2svn * 2063b73463SBrian Somers * $Id: fsm.c,v 1.27 1998/01/20 22:47:36 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn * o Refer loglevel for log output 241ae349f5Scvs2svn * o Better option log display 251ae349f5Scvs2svn */ 261ae349f5Scvs2svn #include <sys/param.h> 271ae349f5Scvs2svn #include <netinet/in.h> 281ae349f5Scvs2svn 291ae349f5Scvs2svn #include <stdio.h> 301ae349f5Scvs2svn #include <string.h> 311ae349f5Scvs2svn #include <termios.h> 321ae349f5Scvs2svn 331ae349f5Scvs2svn #include "command.h" 341ae349f5Scvs2svn #include "mbuf.h" 351ae349f5Scvs2svn #include "log.h" 361ae349f5Scvs2svn #include "defs.h" 371ae349f5Scvs2svn #include "timer.h" 381ae349f5Scvs2svn #include "fsm.h" 391ae349f5Scvs2svn #include "hdlc.h" 401ae349f5Scvs2svn #include "lqr.h" 411ae349f5Scvs2svn #include "lcpproto.h" 421ae349f5Scvs2svn #include "lcp.h" 431ae349f5Scvs2svn #include "ccp.h" 441ae349f5Scvs2svn #include "modem.h" 451ae349f5Scvs2svn #include "loadalias.h" 461ae349f5Scvs2svn #include "vars.h" 4763b73463SBrian Somers #include "physical.h" 481ae349f5Scvs2svn 491ae349f5Scvs2svn u_char AckBuff[200]; 501ae349f5Scvs2svn u_char NakBuff[200]; 511ae349f5Scvs2svn u_char RejBuff[100]; 521ae349f5Scvs2svn u_char ReqBuff[200]; 531ae349f5Scvs2svn u_char *ackp = NULL; 541ae349f5Scvs2svn u_char *nakp = NULL; 551ae349f5Scvs2svn u_char *rejp = NULL; 561ae349f5Scvs2svn 571ae349f5Scvs2svn static void FsmSendConfigReq(struct fsm *); 581ae349f5Scvs2svn static void FsmSendTerminateReq(struct fsm *); 591ae349f5Scvs2svn static void FsmInitRestartCounter(struct fsm *); 601ae349f5Scvs2svn 611ae349f5Scvs2svn char const *StateNames[] = { 621ae349f5Scvs2svn "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 631ae349f5Scvs2svn "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened", 641ae349f5Scvs2svn }; 651ae349f5Scvs2svn 661ae349f5Scvs2svn static void 671ae349f5Scvs2svn StoppedTimeout(void *v) 681ae349f5Scvs2svn { 691ae349f5Scvs2svn struct fsm *fp = (struct fsm *)v; 701ae349f5Scvs2svn 711ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Stopped timer expired\n"); 721ae349f5Scvs2svn if (fp->OpenTimer.state == TIMER_RUNNING) { 731ae349f5Scvs2svn LogPrintf(LogWARN, "%s: aborting open delay due to stopped timer\n", 741ae349f5Scvs2svn fp->name); 751ae349f5Scvs2svn StopTimer(&fp->OpenTimer); 761ae349f5Scvs2svn } 7763b73463SBrian Somers if (Physical_IsActive(fp->physical)) 781ae349f5Scvs2svn DownConnection(); 791ae349f5Scvs2svn else 801ae349f5Scvs2svn FsmDown(fp); 811ae349f5Scvs2svn } 821ae349f5Scvs2svn 831ae349f5Scvs2svn void 8463b73463SBrian Somers FsmInit(struct fsm * fp, struct physical *physical) 851ae349f5Scvs2svn { 861ae349f5Scvs2svn LogPrintf(LogDEBUG, "FsmInit\n"); 871ae349f5Scvs2svn fp->state = ST_INITIAL; 881ae349f5Scvs2svn fp->reqid = 1; 891ae349f5Scvs2svn fp->restart = 1; 901ae349f5Scvs2svn fp->maxconfig = 3; 9163b73463SBrian Somers fp->physical = physical; 921ae349f5Scvs2svn } 931ae349f5Scvs2svn 941ae349f5Scvs2svn static void 951ae349f5Scvs2svn NewState(struct fsm * fp, int new) 961ae349f5Scvs2svn { 971ae349f5Scvs2svn LogPrintf(fp->LogLevel, "State change %s --> %s\n", 981ae349f5Scvs2svn StateNames[fp->state], StateNames[new]); 991ae349f5Scvs2svn if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING) 1001ae349f5Scvs2svn StopTimer(&fp->StoppedTimer); 1011ae349f5Scvs2svn fp->state = new; 1021ae349f5Scvs2svn if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) { 1031ae349f5Scvs2svn StopTimer(&fp->FsmTimer); 1041ae349f5Scvs2svn if (new == ST_STOPPED && fp->StoppedTimer.load) { 1051ae349f5Scvs2svn fp->StoppedTimer.state = TIMER_STOPPED; 1061ae349f5Scvs2svn fp->StoppedTimer.func = StoppedTimeout; 1071ae349f5Scvs2svn fp->StoppedTimer.arg = (void *) fp; 1081ae349f5Scvs2svn StartTimer(&fp->StoppedTimer); 1091ae349f5Scvs2svn } 1101ae349f5Scvs2svn } 1111ae349f5Scvs2svn } 1121ae349f5Scvs2svn 1131ae349f5Scvs2svn void 1141ae349f5Scvs2svn FsmOutput(struct fsm * fp, u_int code, u_int id, u_char * ptr, int count) 1151ae349f5Scvs2svn { 1161ae349f5Scvs2svn int plen; 1171ae349f5Scvs2svn struct fsmheader lh; 1181ae349f5Scvs2svn struct mbuf *bp; 1191ae349f5Scvs2svn 1201ae349f5Scvs2svn plen = sizeof(struct fsmheader) + count; 1211ae349f5Scvs2svn lh.code = code; 1221ae349f5Scvs2svn lh.id = id; 1231ae349f5Scvs2svn lh.length = htons(plen); 1241ae349f5Scvs2svn bp = mballoc(plen, MB_FSM); 1251ae349f5Scvs2svn memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 1261ae349f5Scvs2svn if (count) 1271ae349f5Scvs2svn memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count); 1281ae349f5Scvs2svn LogDumpBp(LogDEBUG, "FsmOutput", bp); 12963b73463SBrian Somers HdlcOutput(fp->physical, PRI_LINK, fp->proto, bp); 1301ae349f5Scvs2svn } 1311ae349f5Scvs2svn 1321ae349f5Scvs2svn static void 1331ae349f5Scvs2svn FsmOpenNow(void *v) 1341ae349f5Scvs2svn { 1351ae349f5Scvs2svn struct fsm *fp = (struct fsm *)v; 1361ae349f5Scvs2svn 1371ae349f5Scvs2svn StopTimer(&fp->OpenTimer); 1381ae349f5Scvs2svn if (fp->state <= ST_STOPPED) { 1391ae349f5Scvs2svn FsmInitRestartCounter(fp); 1401ae349f5Scvs2svn FsmSendConfigReq(fp); 1411ae349f5Scvs2svn NewState(fp, ST_REQSENT); 1421ae349f5Scvs2svn } 1431ae349f5Scvs2svn } 1441ae349f5Scvs2svn 1451ae349f5Scvs2svn void 1461ae349f5Scvs2svn FsmOpen(struct fsm * fp) 1471ae349f5Scvs2svn { 1481ae349f5Scvs2svn switch (fp->state) { 1491ae349f5Scvs2svn case ST_INITIAL: 1501ae349f5Scvs2svn (fp->LayerStart) (fp); 1511ae349f5Scvs2svn NewState(fp, ST_STARTING); 1521ae349f5Scvs2svn break; 1531ae349f5Scvs2svn case ST_STARTING: 1541ae349f5Scvs2svn break; 1551ae349f5Scvs2svn case ST_CLOSED: 1561ae349f5Scvs2svn if (fp->open_mode == OPEN_PASSIVE) { 1571ae349f5Scvs2svn NewState(fp, ST_STOPPED); 1581ae349f5Scvs2svn } else if (fp->open_mode > 0) { 1591ae349f5Scvs2svn if (fp->open_mode > 1) 1601ae349f5Scvs2svn LogPrintf(LogPHASE, "Entering STOPPED state for %d seconds\n", 1611ae349f5Scvs2svn fp->open_mode); 1621ae349f5Scvs2svn NewState(fp, ST_STOPPED); 1631ae349f5Scvs2svn fp->OpenTimer.state = TIMER_STOPPED; 1641ae349f5Scvs2svn fp->OpenTimer.load = fp->open_mode * SECTICKS; 1651ae349f5Scvs2svn fp->OpenTimer.func = FsmOpenNow; 1661ae349f5Scvs2svn fp->OpenTimer.arg = (void *)fp; 1671ae349f5Scvs2svn StartTimer(&fp->OpenTimer); 1681ae349f5Scvs2svn } else 1691ae349f5Scvs2svn FsmOpenNow(fp); 1701ae349f5Scvs2svn break; 1711ae349f5Scvs2svn case ST_STOPPED: /* XXX: restart option */ 1721ae349f5Scvs2svn case ST_REQSENT: 1731ae349f5Scvs2svn case ST_ACKRCVD: 1741ae349f5Scvs2svn case ST_ACKSENT: 1751ae349f5Scvs2svn case ST_OPENED: /* XXX: restart option */ 1761ae349f5Scvs2svn break; 1771ae349f5Scvs2svn case ST_CLOSING: /* XXX: restart option */ 1781ae349f5Scvs2svn case ST_STOPPING: /* XXX: restart option */ 1791ae349f5Scvs2svn NewState(fp, ST_STOPPING); 1801ae349f5Scvs2svn break; 1811ae349f5Scvs2svn } 1821ae349f5Scvs2svn } 1831ae349f5Scvs2svn 1841ae349f5Scvs2svn void 1851ae349f5Scvs2svn FsmUp(struct fsm * fp) 1861ae349f5Scvs2svn { 1871ae349f5Scvs2svn switch (fp->state) { 1881ae349f5Scvs2svn case ST_INITIAL: 1891ae349f5Scvs2svn NewState(fp, ST_CLOSED); 1901ae349f5Scvs2svn break; 1911ae349f5Scvs2svn case ST_STARTING: 1921ae349f5Scvs2svn FsmInitRestartCounter(fp); 1931ae349f5Scvs2svn FsmSendConfigReq(fp); 1941ae349f5Scvs2svn NewState(fp, ST_REQSENT); 1951ae349f5Scvs2svn break; 1961ae349f5Scvs2svn default: 1971ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]); 1981ae349f5Scvs2svn break; 1991ae349f5Scvs2svn } 2001ae349f5Scvs2svn } 2011ae349f5Scvs2svn 2021ae349f5Scvs2svn void 2031ae349f5Scvs2svn FsmDown(struct fsm * fp) 2041ae349f5Scvs2svn { 2051ae349f5Scvs2svn switch (fp->state) { 2061ae349f5Scvs2svn case ST_CLOSED: 2071ae349f5Scvs2svn case ST_CLOSING: 2081ae349f5Scvs2svn NewState(fp, ST_INITIAL); 2091ae349f5Scvs2svn break; 2101ae349f5Scvs2svn case ST_STOPPED: 2111ae349f5Scvs2svn (fp->LayerStart) (fp); 2121ae349f5Scvs2svn /* Fall into.. */ 2131ae349f5Scvs2svn case ST_STOPPING: 2141ae349f5Scvs2svn case ST_REQSENT: 2151ae349f5Scvs2svn case ST_ACKRCVD: 2161ae349f5Scvs2svn case ST_ACKSENT: 2171ae349f5Scvs2svn NewState(fp, ST_STARTING); 2181ae349f5Scvs2svn break; 2191ae349f5Scvs2svn case ST_OPENED: 2201ae349f5Scvs2svn (fp->LayerDown) (fp); 2211ae349f5Scvs2svn NewState(fp, ST_STARTING); 2221ae349f5Scvs2svn break; 2231ae349f5Scvs2svn } 2241ae349f5Scvs2svn } 2251ae349f5Scvs2svn 2261ae349f5Scvs2svn void 2271ae349f5Scvs2svn FsmClose(struct fsm * fp) 2281ae349f5Scvs2svn { 2291ae349f5Scvs2svn switch (fp->state) { 2301ae349f5Scvs2svn case ST_STARTING: 2311ae349f5Scvs2svn NewState(fp, ST_INITIAL); 2321ae349f5Scvs2svn break; 2331ae349f5Scvs2svn case ST_STOPPED: 2341ae349f5Scvs2svn NewState(fp, ST_CLOSED); 2351ae349f5Scvs2svn break; 2361ae349f5Scvs2svn case ST_STOPPING: 2371ae349f5Scvs2svn NewState(fp, ST_CLOSING); 2381ae349f5Scvs2svn break; 2391ae349f5Scvs2svn case ST_OPENED: 2401ae349f5Scvs2svn (fp->LayerDown) (fp); 2411ae349f5Scvs2svn /* Fall down */ 2421ae349f5Scvs2svn case ST_REQSENT: 2431ae349f5Scvs2svn case ST_ACKRCVD: 2441ae349f5Scvs2svn case ST_ACKSENT: 2451ae349f5Scvs2svn FsmInitRestartCounter(fp); 2461ae349f5Scvs2svn FsmSendTerminateReq(fp); 2471ae349f5Scvs2svn NewState(fp, ST_CLOSING); 2481ae349f5Scvs2svn break; 2491ae349f5Scvs2svn } 2501ae349f5Scvs2svn } 2511ae349f5Scvs2svn 2521ae349f5Scvs2svn /* 2531ae349f5Scvs2svn * Send functions 2541ae349f5Scvs2svn */ 2551ae349f5Scvs2svn static void 2561ae349f5Scvs2svn FsmSendConfigReq(struct fsm * fp) 2571ae349f5Scvs2svn { 2581ae349f5Scvs2svn if (--fp->maxconfig > 0) { 2591ae349f5Scvs2svn (fp->SendConfigReq) (fp); 2601ae349f5Scvs2svn StartTimer(&fp->FsmTimer); /* Start restart timer */ 2611ae349f5Scvs2svn fp->restart--; /* Decrement restart counter */ 2621ae349f5Scvs2svn } else { 2631ae349f5Scvs2svn FsmClose(fp); 2641ae349f5Scvs2svn } 2651ae349f5Scvs2svn } 2661ae349f5Scvs2svn 2671ae349f5Scvs2svn static void 2681ae349f5Scvs2svn FsmSendTerminateReq(struct fsm * fp) 2691ae349f5Scvs2svn { 2701ae349f5Scvs2svn LogPrintf(fp->LogLevel, "SendTerminateReq.\n"); 2711ae349f5Scvs2svn FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0); 2721ae349f5Scvs2svn (fp->SendTerminateReq) (fp); 2731ae349f5Scvs2svn StartTimer(&fp->FsmTimer); /* Start restart timer */ 2741ae349f5Scvs2svn fp->restart--; /* Decrement restart counter */ 2751ae349f5Scvs2svn } 2761ae349f5Scvs2svn 2771ae349f5Scvs2svn static void 2781ae349f5Scvs2svn FsmSendConfigAck(struct fsm * fp, 2791ae349f5Scvs2svn struct fsmheader * lhp, 2801ae349f5Scvs2svn u_char * option, 2811ae349f5Scvs2svn int count) 2821ae349f5Scvs2svn { 2831ae349f5Scvs2svn LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]); 2841ae349f5Scvs2svn (fp->DecodeConfig) (option, count, MODE_NOP); 2851ae349f5Scvs2svn FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count); 2861ae349f5Scvs2svn } 2871ae349f5Scvs2svn 2881ae349f5Scvs2svn static void 2891ae349f5Scvs2svn FsmSendConfigRej(struct fsm * fp, 2901ae349f5Scvs2svn struct fsmheader * lhp, 2911ae349f5Scvs2svn u_char * option, 2921ae349f5Scvs2svn int count) 2931ae349f5Scvs2svn { 2941ae349f5Scvs2svn LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]); 2951ae349f5Scvs2svn (fp->DecodeConfig) (option, count, MODE_NOP); 2961ae349f5Scvs2svn FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count); 2971ae349f5Scvs2svn } 2981ae349f5Scvs2svn 2991ae349f5Scvs2svn static void 3001ae349f5Scvs2svn FsmSendConfigNak(struct fsm * fp, 3011ae349f5Scvs2svn struct fsmheader * lhp, 3021ae349f5Scvs2svn u_char * option, 3031ae349f5Scvs2svn int count) 3041ae349f5Scvs2svn { 3051ae349f5Scvs2svn LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]); 3061ae349f5Scvs2svn (fp->DecodeConfig) (option, count, MODE_NOP); 3071ae349f5Scvs2svn FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count); 3081ae349f5Scvs2svn } 3091ae349f5Scvs2svn 3101ae349f5Scvs2svn /* 3111ae349f5Scvs2svn * Timeout actions 3121ae349f5Scvs2svn */ 3131ae349f5Scvs2svn static void 3141ae349f5Scvs2svn FsmTimeout(void *v) 3151ae349f5Scvs2svn { 3161ae349f5Scvs2svn struct fsm *fp = (struct fsm *)v; 3171ae349f5Scvs2svn 3181ae349f5Scvs2svn if (fp->restart) { 3191ae349f5Scvs2svn switch (fp->state) { 3201ae349f5Scvs2svn case ST_CLOSING: 3211ae349f5Scvs2svn case ST_STOPPING: 3221ae349f5Scvs2svn FsmSendTerminateReq(fp); 3231ae349f5Scvs2svn break; 3241ae349f5Scvs2svn case ST_REQSENT: 3251ae349f5Scvs2svn case ST_ACKSENT: 3261ae349f5Scvs2svn FsmSendConfigReq(fp); 3271ae349f5Scvs2svn break; 3281ae349f5Scvs2svn case ST_ACKRCVD: 3291ae349f5Scvs2svn FsmSendConfigReq(fp); 3301ae349f5Scvs2svn NewState(fp, ST_REQSENT); 3311ae349f5Scvs2svn break; 3321ae349f5Scvs2svn } 3331ae349f5Scvs2svn StartTimer(&fp->FsmTimer); 3341ae349f5Scvs2svn } else { 3351ae349f5Scvs2svn switch (fp->state) { 3361ae349f5Scvs2svn case ST_CLOSING: 3371ae349f5Scvs2svn NewState(fp, ST_CLOSED); 3381ae349f5Scvs2svn (fp->LayerFinish) (fp); 3391ae349f5Scvs2svn break; 3401ae349f5Scvs2svn case ST_STOPPING: 3411ae349f5Scvs2svn NewState(fp, ST_STOPPED); 3421ae349f5Scvs2svn (fp->LayerFinish) (fp); 3431ae349f5Scvs2svn break; 3441ae349f5Scvs2svn case ST_REQSENT: /* XXX: 3p */ 3451ae349f5Scvs2svn case ST_ACKSENT: 3461ae349f5Scvs2svn case ST_ACKRCVD: 3471ae349f5Scvs2svn NewState(fp, ST_STOPPED); 3481ae349f5Scvs2svn (fp->LayerFinish) (fp); 3491ae349f5Scvs2svn break; 3501ae349f5Scvs2svn } 3511ae349f5Scvs2svn } 3521ae349f5Scvs2svn } 3531ae349f5Scvs2svn 3541ae349f5Scvs2svn static void 3551ae349f5Scvs2svn FsmInitRestartCounter(struct fsm * fp) 3561ae349f5Scvs2svn { 3571ae349f5Scvs2svn StopTimer(&fp->FsmTimer); 3581ae349f5Scvs2svn fp->FsmTimer.state = TIMER_STOPPED; 3591ae349f5Scvs2svn fp->FsmTimer.func = FsmTimeout; 3601ae349f5Scvs2svn fp->FsmTimer.arg = (void *) fp; 3611ae349f5Scvs2svn (fp->InitRestartCounter) (fp); 3621ae349f5Scvs2svn } 3631ae349f5Scvs2svn 3641ae349f5Scvs2svn /* 3651ae349f5Scvs2svn * Actions when receive packets 3661ae349f5Scvs2svn */ 3671ae349f5Scvs2svn static void 3681ae349f5Scvs2svn FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 3691ae349f5Scvs2svn /* RCR */ 3701ae349f5Scvs2svn { 3711ae349f5Scvs2svn int plen, flen; 3721ae349f5Scvs2svn int ackaction = 0; 3731ae349f5Scvs2svn 3741ae349f5Scvs2svn plen = plength(bp); 3751ae349f5Scvs2svn flen = ntohs(lhp->length) - sizeof *lhp; 3761ae349f5Scvs2svn if (plen < flen) { 3771ae349f5Scvs2svn LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)\n", 3781ae349f5Scvs2svn plen, flen); 3791ae349f5Scvs2svn pfree(bp); 3801ae349f5Scvs2svn return; 3811ae349f5Scvs2svn } 3821ae349f5Scvs2svn 3831ae349f5Scvs2svn /* 3841ae349f5Scvs2svn * Check and process easy case 3851ae349f5Scvs2svn */ 3861ae349f5Scvs2svn switch (fp->state) { 3871ae349f5Scvs2svn case ST_INITIAL: 3881ae349f5Scvs2svn case ST_STARTING: 3891ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]); 3901ae349f5Scvs2svn pfree(bp); 3911ae349f5Scvs2svn return; 3921ae349f5Scvs2svn case ST_CLOSED: 3931ae349f5Scvs2svn (fp->SendTerminateAck) (fp); 3941ae349f5Scvs2svn pfree(bp); 3951ae349f5Scvs2svn return; 3961ae349f5Scvs2svn case ST_CLOSING: 3971ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Error: Got ConfigReq while state = %d\n", 3981ae349f5Scvs2svn fp->state); 3991ae349f5Scvs2svn case ST_STOPPING: 4001ae349f5Scvs2svn pfree(bp); 4011ae349f5Scvs2svn return; 4021ae349f5Scvs2svn } 4031ae349f5Scvs2svn 4041ae349f5Scvs2svn (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REQ); 4051ae349f5Scvs2svn 4061ae349f5Scvs2svn if (nakp == NakBuff && rejp == RejBuff) 4071ae349f5Scvs2svn ackaction = 1; 4081ae349f5Scvs2svn 4091ae349f5Scvs2svn switch (fp->state) { 4101ae349f5Scvs2svn case ST_OPENED: 4111ae349f5Scvs2svn (fp->LayerDown) (fp); 4121ae349f5Scvs2svn FsmSendConfigReq(fp); 4131ae349f5Scvs2svn break; 4141ae349f5Scvs2svn case ST_STOPPED: 4151ae349f5Scvs2svn FsmInitRestartCounter(fp); 4161ae349f5Scvs2svn FsmSendConfigReq(fp); 4171ae349f5Scvs2svn break; 4181ae349f5Scvs2svn } 4191ae349f5Scvs2svn 4201ae349f5Scvs2svn if (rejp != RejBuff) 4211ae349f5Scvs2svn FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff); 4221ae349f5Scvs2svn if (nakp != NakBuff) 4231ae349f5Scvs2svn FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff); 4241ae349f5Scvs2svn if (ackaction) 4251ae349f5Scvs2svn FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff); 4261ae349f5Scvs2svn 4271ae349f5Scvs2svn switch (fp->state) { 4281ae349f5Scvs2svn case ST_STOPPED: 4291ae349f5Scvs2svn case ST_OPENED: 4301ae349f5Scvs2svn if (ackaction) 4311ae349f5Scvs2svn NewState(fp, ST_ACKSENT); 4321ae349f5Scvs2svn else 4331ae349f5Scvs2svn NewState(fp, ST_REQSENT); 4341ae349f5Scvs2svn break; 4351ae349f5Scvs2svn case ST_REQSENT: 4361ae349f5Scvs2svn if (ackaction) 4371ae349f5Scvs2svn NewState(fp, ST_ACKSENT); 4381ae349f5Scvs2svn break; 4391ae349f5Scvs2svn case ST_ACKRCVD: 4401ae349f5Scvs2svn if (ackaction) { 4411ae349f5Scvs2svn NewState(fp, ST_OPENED); 4421ae349f5Scvs2svn (fp->LayerUp) (fp); 4431ae349f5Scvs2svn } 4441ae349f5Scvs2svn break; 4451ae349f5Scvs2svn case ST_ACKSENT: 4461ae349f5Scvs2svn if (!ackaction) 4471ae349f5Scvs2svn NewState(fp, ST_REQSENT); 4481ae349f5Scvs2svn break; 4491ae349f5Scvs2svn } 4501ae349f5Scvs2svn pfree(bp); 4511ae349f5Scvs2svn } 4521ae349f5Scvs2svn 4531ae349f5Scvs2svn static void 4541ae349f5Scvs2svn FsmRecvConfigAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 4551ae349f5Scvs2svn /* RCA */ 4561ae349f5Scvs2svn { 4571ae349f5Scvs2svn switch (fp->state) { 4581ae349f5Scvs2svn case ST_CLOSED: 4591ae349f5Scvs2svn case ST_STOPPED: 4601ae349f5Scvs2svn (fp->SendTerminateAck) (fp); 4611ae349f5Scvs2svn break; 4621ae349f5Scvs2svn case ST_CLOSING: 4631ae349f5Scvs2svn case ST_STOPPING: 4641ae349f5Scvs2svn break; 4651ae349f5Scvs2svn case ST_REQSENT: 4661ae349f5Scvs2svn FsmInitRestartCounter(fp); 4671ae349f5Scvs2svn NewState(fp, ST_ACKRCVD); 4681ae349f5Scvs2svn break; 4691ae349f5Scvs2svn case ST_ACKRCVD: 4701ae349f5Scvs2svn FsmSendConfigReq(fp); 4711ae349f5Scvs2svn NewState(fp, ST_REQSENT); 4721ae349f5Scvs2svn break; 4731ae349f5Scvs2svn case ST_ACKSENT: 4741ae349f5Scvs2svn FsmInitRestartCounter(fp); 4751ae349f5Scvs2svn NewState(fp, ST_OPENED); 4761ae349f5Scvs2svn (fp->LayerUp) (fp); 4771ae349f5Scvs2svn break; 4781ae349f5Scvs2svn case ST_OPENED: 4791ae349f5Scvs2svn (fp->LayerDown) (fp); 4801ae349f5Scvs2svn FsmSendConfigReq(fp); 4811ae349f5Scvs2svn NewState(fp, ST_REQSENT); 4821ae349f5Scvs2svn break; 4831ae349f5Scvs2svn } 4841ae349f5Scvs2svn pfree(bp); 4851ae349f5Scvs2svn } 4861ae349f5Scvs2svn 4871ae349f5Scvs2svn static void 4881ae349f5Scvs2svn FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 4891ae349f5Scvs2svn /* RCN */ 4901ae349f5Scvs2svn { 4911ae349f5Scvs2svn int plen, flen; 4921ae349f5Scvs2svn 4931ae349f5Scvs2svn plen = plength(bp); 4941ae349f5Scvs2svn flen = ntohs(lhp->length) - sizeof *lhp; 4951ae349f5Scvs2svn if (plen < flen) { 4961ae349f5Scvs2svn pfree(bp); 4971ae349f5Scvs2svn return; 4981ae349f5Scvs2svn } 4991ae349f5Scvs2svn 5001ae349f5Scvs2svn /* 5011ae349f5Scvs2svn * Check and process easy case 5021ae349f5Scvs2svn */ 5031ae349f5Scvs2svn switch (fp->state) { 5041ae349f5Scvs2svn case ST_INITIAL: 5051ae349f5Scvs2svn case ST_STARTING: 5061ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", StateNames[fp->state]); 5071ae349f5Scvs2svn pfree(bp); 5081ae349f5Scvs2svn return; 5091ae349f5Scvs2svn case ST_CLOSED: 5101ae349f5Scvs2svn case ST_STOPPED: 5111ae349f5Scvs2svn (fp->SendTerminateAck) (fp); 5121ae349f5Scvs2svn pfree(bp); 5131ae349f5Scvs2svn return; 5141ae349f5Scvs2svn case ST_CLOSING: 5151ae349f5Scvs2svn case ST_STOPPING: 5161ae349f5Scvs2svn pfree(bp); 5171ae349f5Scvs2svn return; 5181ae349f5Scvs2svn } 5191ae349f5Scvs2svn 5201ae349f5Scvs2svn (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_NAK); 5211ae349f5Scvs2svn 5221ae349f5Scvs2svn switch (fp->state) { 5231ae349f5Scvs2svn case ST_REQSENT: 5241ae349f5Scvs2svn case ST_ACKSENT: 5251ae349f5Scvs2svn FsmInitRestartCounter(fp); 5261ae349f5Scvs2svn FsmSendConfigReq(fp); 5271ae349f5Scvs2svn break; 5281ae349f5Scvs2svn case ST_OPENED: 5291ae349f5Scvs2svn (fp->LayerDown) (fp); 5301ae349f5Scvs2svn /* Fall down */ 5311ae349f5Scvs2svn case ST_ACKRCVD: 5321ae349f5Scvs2svn FsmSendConfigReq(fp); 5331ae349f5Scvs2svn NewState(fp, ST_REQSENT); 5341ae349f5Scvs2svn break; 5351ae349f5Scvs2svn } 5361ae349f5Scvs2svn 5371ae349f5Scvs2svn pfree(bp); 5381ae349f5Scvs2svn } 5391ae349f5Scvs2svn 5401ae349f5Scvs2svn static void 5411ae349f5Scvs2svn FsmRecvTermReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 5421ae349f5Scvs2svn /* RTR */ 5431ae349f5Scvs2svn { 5441ae349f5Scvs2svn switch (fp->state) { 5451ae349f5Scvs2svn case ST_INITIAL: 5461ae349f5Scvs2svn case ST_STARTING: 5471ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", StateNames[fp->state]); 5481ae349f5Scvs2svn break; 5491ae349f5Scvs2svn case ST_CLOSED: 5501ae349f5Scvs2svn case ST_STOPPED: 5511ae349f5Scvs2svn case ST_CLOSING: 5521ae349f5Scvs2svn case ST_STOPPING: 5531ae349f5Scvs2svn case ST_REQSENT: 5541ae349f5Scvs2svn (fp->SendTerminateAck) (fp); 5551ae349f5Scvs2svn break; 5561ae349f5Scvs2svn case ST_ACKRCVD: 5571ae349f5Scvs2svn case ST_ACKSENT: 5581ae349f5Scvs2svn (fp->SendTerminateAck) (fp); 5591ae349f5Scvs2svn NewState(fp, ST_REQSENT); 5601ae349f5Scvs2svn break; 5611ae349f5Scvs2svn case ST_OPENED: 5621ae349f5Scvs2svn (fp->LayerDown) (fp); 5631ae349f5Scvs2svn (fp->SendTerminateAck) (fp); 5641ae349f5Scvs2svn StartTimer(&fp->FsmTimer); /* Start restart timer */ 5651ae349f5Scvs2svn fp->restart = 0; 5661ae349f5Scvs2svn NewState(fp, ST_STOPPING); 5671ae349f5Scvs2svn break; 5681ae349f5Scvs2svn } 5691ae349f5Scvs2svn pfree(bp); 5701ae349f5Scvs2svn } 5711ae349f5Scvs2svn 5721ae349f5Scvs2svn static void 5731ae349f5Scvs2svn FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 5741ae349f5Scvs2svn /* RTA */ 5751ae349f5Scvs2svn { 5761ae349f5Scvs2svn switch (fp->state) { 5771ae349f5Scvs2svn case ST_CLOSING: 5781ae349f5Scvs2svn NewState(fp, ST_CLOSED); 5791ae349f5Scvs2svn (fp->LayerFinish) (fp); 5801ae349f5Scvs2svn break; 5811ae349f5Scvs2svn case ST_STOPPING: 5821ae349f5Scvs2svn NewState(fp, ST_STOPPED); 5831ae349f5Scvs2svn (fp->LayerFinish) (fp); 5841ae349f5Scvs2svn break; 5851ae349f5Scvs2svn case ST_ACKRCVD: 5861ae349f5Scvs2svn NewState(fp, ST_REQSENT); 5871ae349f5Scvs2svn break; 5881ae349f5Scvs2svn case ST_OPENED: 5891ae349f5Scvs2svn (fp->LayerDown) (fp); 5901ae349f5Scvs2svn FsmSendConfigReq(fp); 5911ae349f5Scvs2svn NewState(fp, ST_REQSENT); 5921ae349f5Scvs2svn break; 5931ae349f5Scvs2svn } 5941ae349f5Scvs2svn pfree(bp); 5951ae349f5Scvs2svn } 5961ae349f5Scvs2svn 5971ae349f5Scvs2svn static void 5981ae349f5Scvs2svn FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 5991ae349f5Scvs2svn /* RCJ */ 6001ae349f5Scvs2svn { 6011ae349f5Scvs2svn int plen, flen; 6021ae349f5Scvs2svn 6031ae349f5Scvs2svn plen = plength(bp); 6041ae349f5Scvs2svn flen = ntohs(lhp->length) - sizeof *lhp; 6051ae349f5Scvs2svn if (plen < flen) { 6061ae349f5Scvs2svn pfree(bp); 6071ae349f5Scvs2svn return; 6081ae349f5Scvs2svn } 6091ae349f5Scvs2svn LogPrintf(fp->LogLevel, "RecvConfigRej.\n"); 6101ae349f5Scvs2svn 6111ae349f5Scvs2svn /* 6121ae349f5Scvs2svn * Check and process easy case 6131ae349f5Scvs2svn */ 6141ae349f5Scvs2svn switch (fp->state) { 6151ae349f5Scvs2svn case ST_INITIAL: 6161ae349f5Scvs2svn case ST_STARTING: 6171ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", StateNames[fp->state]); 6181ae349f5Scvs2svn pfree(bp); 6191ae349f5Scvs2svn return; 6201ae349f5Scvs2svn case ST_CLOSED: 6211ae349f5Scvs2svn case ST_STOPPED: 6221ae349f5Scvs2svn (fp->SendTerminateAck) (fp); 6231ae349f5Scvs2svn pfree(bp); 6241ae349f5Scvs2svn return; 6251ae349f5Scvs2svn case ST_CLOSING: 6261ae349f5Scvs2svn case ST_STOPPING: 6271ae349f5Scvs2svn pfree(bp); 6281ae349f5Scvs2svn return; 6291ae349f5Scvs2svn } 6301ae349f5Scvs2svn 6311ae349f5Scvs2svn (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REJ); 6321ae349f5Scvs2svn 6331ae349f5Scvs2svn switch (fp->state) { 6341ae349f5Scvs2svn case ST_REQSENT: 6351ae349f5Scvs2svn case ST_ACKSENT: 6361ae349f5Scvs2svn FsmInitRestartCounter(fp); 6371ae349f5Scvs2svn FsmSendConfigReq(fp); 6381ae349f5Scvs2svn break; 6391ae349f5Scvs2svn case ST_OPENED: 6401ae349f5Scvs2svn (fp->LayerDown) (fp); 6411ae349f5Scvs2svn /* Fall down */ 6421ae349f5Scvs2svn case ST_ACKRCVD: 6431ae349f5Scvs2svn FsmSendConfigReq(fp); 6441ae349f5Scvs2svn NewState(fp, ST_REQSENT); 6451ae349f5Scvs2svn break; 6461ae349f5Scvs2svn } 6471ae349f5Scvs2svn pfree(bp); 6481ae349f5Scvs2svn } 6491ae349f5Scvs2svn 6501ae349f5Scvs2svn static void 6511ae349f5Scvs2svn FsmRecvCodeRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 6521ae349f5Scvs2svn { 6531ae349f5Scvs2svn LogPrintf(fp->LogLevel, "RecvCodeRej\n"); 6541ae349f5Scvs2svn pfree(bp); 6551ae349f5Scvs2svn } 6561ae349f5Scvs2svn 6571ae349f5Scvs2svn static void 6581ae349f5Scvs2svn FsmRecvProtoRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 6591ae349f5Scvs2svn { 6601ae349f5Scvs2svn u_short *sp, proto; 6611ae349f5Scvs2svn 6621ae349f5Scvs2svn sp = (u_short *) MBUF_CTOP(bp); 6631ae349f5Scvs2svn proto = ntohs(*sp); 6641ae349f5Scvs2svn LogPrintf(fp->LogLevel, "-- Protocol (%04x) was rejected.\n", proto); 6651ae349f5Scvs2svn 6661ae349f5Scvs2svn switch (proto) { 6671ae349f5Scvs2svn case PROTO_LQR: 66863b73463SBrian Somers StopLqr(fp->physical, LQM_LQR); 6691ae349f5Scvs2svn break; 6701ae349f5Scvs2svn case PROTO_CCP: 6711ae349f5Scvs2svn fp = &CcpFsm; 6721ae349f5Scvs2svn (fp->LayerFinish) (fp); 6731ae349f5Scvs2svn switch (fp->state) { 6741ae349f5Scvs2svn case ST_CLOSED: 6751ae349f5Scvs2svn case ST_CLOSING: 6761ae349f5Scvs2svn NewState(fp, ST_CLOSED); 6771ae349f5Scvs2svn default: 6781ae349f5Scvs2svn NewState(fp, ST_STOPPED); 6791ae349f5Scvs2svn break; 6801ae349f5Scvs2svn } 6811ae349f5Scvs2svn break; 6821ae349f5Scvs2svn } 6831ae349f5Scvs2svn pfree(bp); 6841ae349f5Scvs2svn } 6851ae349f5Scvs2svn 6861ae349f5Scvs2svn static void 6871ae349f5Scvs2svn FsmRecvEchoReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 6881ae349f5Scvs2svn { 6891ae349f5Scvs2svn u_char *cp; 6901ae349f5Scvs2svn u_long *lp, magic; 6911ae349f5Scvs2svn 6921ae349f5Scvs2svn cp = MBUF_CTOP(bp); 6931ae349f5Scvs2svn lp = (u_long *) cp; 6941ae349f5Scvs2svn magic = ntohl(*lp); 6951ae349f5Scvs2svn if (magic != LcpInfo.his_magic) { 6961ae349f5Scvs2svn LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n"); 6971ae349f5Scvs2svn /* XXX: We should send terminate request */ 6981ae349f5Scvs2svn } 6991ae349f5Scvs2svn if (fp->state == ST_OPENED) { 7001ae349f5Scvs2svn *lp = htonl(LcpInfo.want_magic); /* Insert local magic number */ 7011ae349f5Scvs2svn LogPrintf(fp->LogLevel, "SendEchoRep(%s)\n", StateNames[fp->state]); 7021ae349f5Scvs2svn FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp)); 7031ae349f5Scvs2svn } 7041ae349f5Scvs2svn pfree(bp); 7051ae349f5Scvs2svn } 7061ae349f5Scvs2svn 7071ae349f5Scvs2svn static void 7081ae349f5Scvs2svn FsmRecvEchoRep(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 7091ae349f5Scvs2svn { 7101ae349f5Scvs2svn u_long *lp, magic; 7111ae349f5Scvs2svn 7121ae349f5Scvs2svn lp = (u_long *) MBUF_CTOP(bp); 7131ae349f5Scvs2svn magic = ntohl(*lp); 7141ae349f5Scvs2svn /* 7151ae349f5Scvs2svn * Tolerate echo replies with either magic number 7161ae349f5Scvs2svn */ 7171ae349f5Scvs2svn if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) { 7181ae349f5Scvs2svn LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n", 7191ae349f5Scvs2svn LcpInfo.his_magic, magic); 7201ae349f5Scvs2svn 7211ae349f5Scvs2svn /* 7221ae349f5Scvs2svn * XXX: We should send terminate request. But poor implementation may die 7231ae349f5Scvs2svn * as a result. 7241ae349f5Scvs2svn */ 7251ae349f5Scvs2svn } 7261ae349f5Scvs2svn RecvEchoLqr(bp); 7271ae349f5Scvs2svn pfree(bp); 7281ae349f5Scvs2svn } 7291ae349f5Scvs2svn 7301ae349f5Scvs2svn static void 7311ae349f5Scvs2svn FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 7321ae349f5Scvs2svn { 7331ae349f5Scvs2svn LogPrintf(fp->LogLevel, "RecvDiscReq\n"); 7341ae349f5Scvs2svn pfree(bp); 7351ae349f5Scvs2svn } 7361ae349f5Scvs2svn 7371ae349f5Scvs2svn static void 7381ae349f5Scvs2svn FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 7391ae349f5Scvs2svn { 7401ae349f5Scvs2svn LogPrintf(fp->LogLevel, "RecvIdent\n"); 7411ae349f5Scvs2svn pfree(bp); 7421ae349f5Scvs2svn } 7431ae349f5Scvs2svn 7441ae349f5Scvs2svn static void 7451ae349f5Scvs2svn FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 7461ae349f5Scvs2svn { 7471ae349f5Scvs2svn LogPrintf(fp->LogLevel, "RecvTimeRemain\n"); 7481ae349f5Scvs2svn pfree(bp); 7491ae349f5Scvs2svn } 7501ae349f5Scvs2svn 7511ae349f5Scvs2svn static void 7521ae349f5Scvs2svn FsmRecvResetReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 7531ae349f5Scvs2svn { 7541ae349f5Scvs2svn LogPrintf(fp->LogLevel, "RecvResetReq(%d)\n", lhp->id); 7551ae349f5Scvs2svn CcpRecvResetReq(fp); 7561ae349f5Scvs2svn /* 7571ae349f5Scvs2svn * All sendable compressed packets are queued in the PRI_NORMAL modem 7581ae349f5Scvs2svn * output queue.... dump 'em to the priority queue so that they arrive 7591ae349f5Scvs2svn * at the peer before our ResetAck. 7601ae349f5Scvs2svn */ 76163b73463SBrian Somers SequenceQueues(fp->physical); 7621ae349f5Scvs2svn LogPrintf(fp->LogLevel, "SendResetAck(%d)\n", lhp->id); 7631ae349f5Scvs2svn FsmOutput(fp, CODE_RESETACK, lhp->id, NULL, 0); 7641ae349f5Scvs2svn pfree(bp); 7651ae349f5Scvs2svn } 7661ae349f5Scvs2svn 7671ae349f5Scvs2svn static void 7681ae349f5Scvs2svn FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 7691ae349f5Scvs2svn { 7701ae349f5Scvs2svn LogPrintf(fp->LogLevel, "RecvResetAck(%d)\n", lhp->id); 7711ae349f5Scvs2svn CcpResetInput(lhp->id); 7721ae349f5Scvs2svn fp->reqid++; 7731ae349f5Scvs2svn pfree(bp); 7741ae349f5Scvs2svn } 7751ae349f5Scvs2svn 7761ae349f5Scvs2svn static const struct fsmcodedesc FsmCodes[] = { 7771ae349f5Scvs2svn {FsmRecvConfigReq, "Configure Request",}, 7781ae349f5Scvs2svn {FsmRecvConfigAck, "Configure Ack",}, 7791ae349f5Scvs2svn {FsmRecvConfigNak, "Configure Nak",}, 7801ae349f5Scvs2svn {FsmRecvConfigRej, "Configure Reject",}, 7811ae349f5Scvs2svn {FsmRecvTermReq, "Terminate Request",}, 7821ae349f5Scvs2svn {FsmRecvTermAck, "Terminate Ack",}, 7831ae349f5Scvs2svn {FsmRecvCodeRej, "Code Reject",}, 7841ae349f5Scvs2svn {FsmRecvProtoRej, "Protocol Reject",}, 7851ae349f5Scvs2svn {FsmRecvEchoReq, "Echo Request",}, 7861ae349f5Scvs2svn {FsmRecvEchoRep, "Echo Reply",}, 7871ae349f5Scvs2svn {FsmRecvDiscReq, "Discard Request",}, 7881ae349f5Scvs2svn {FsmRecvIdent, "Ident",}, 7891ae349f5Scvs2svn {FsmRecvTimeRemain, "Time Remain",}, 7901ae349f5Scvs2svn {FsmRecvResetReq, "Reset Request",}, 7911ae349f5Scvs2svn {FsmRecvResetAck, "Reset Ack",}, 7921ae349f5Scvs2svn }; 7931ae349f5Scvs2svn 7941ae349f5Scvs2svn void 7951ae349f5Scvs2svn FsmInput(struct fsm * fp, struct mbuf * bp) 7961ae349f5Scvs2svn { 7971ae349f5Scvs2svn int len; 7981ae349f5Scvs2svn struct fsmheader *lhp; 7991ae349f5Scvs2svn const struct fsmcodedesc *codep; 8001ae349f5Scvs2svn 8011ae349f5Scvs2svn len = plength(bp); 8021ae349f5Scvs2svn if (len < sizeof(struct fsmheader)) { 8031ae349f5Scvs2svn pfree(bp); 8041ae349f5Scvs2svn return; 8051ae349f5Scvs2svn } 8061ae349f5Scvs2svn lhp = (struct fsmheader *) MBUF_CTOP(bp); 8071ae349f5Scvs2svn if (lhp->code == 0 || lhp->code > fp->max_code) { 8081ae349f5Scvs2svn pfree(bp); /* XXX: Should send code reject */ 8091ae349f5Scvs2svn return; 8101ae349f5Scvs2svn } 8111ae349f5Scvs2svn bp->offset += sizeof(struct fsmheader); 8121ae349f5Scvs2svn bp->cnt -= sizeof(struct fsmheader); 8131ae349f5Scvs2svn 8141ae349f5Scvs2svn codep = FsmCodes + lhp->code - 1; 8151ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n", 8161ae349f5Scvs2svn codep->name, lhp->id, StateNames[fp->state], fp->state); 8171ae349f5Scvs2svn if (LogIsKept(LogDEBUG)) 8181ae349f5Scvs2svn LogMemory(); 8191ae349f5Scvs2svn (codep->action) (fp, lhp, bp); 8201ae349f5Scvs2svn if (LogIsKept(LogDEBUG)) 8211ae349f5Scvs2svn LogMemory(); 8221ae349f5Scvs2svn } 823