fsm.c revision 6059
16059Samurai/* 26059Samurai * PPP Finite State Machine for LCP/IPCP 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 196059Samurai * 206059Samurai * $Id:$ 216059Samurai * 226059Samurai * TODO: 236059Samurai * o Refer loglevel for log output 246059Samurai * o Better option log display 256059Samurai */ 266059Samurai#include "fsm.h" 276059Samurai#include "hdlc.h" 286059Samurai#include "lqr.h" 296059Samurai#include "lcpproto.h" 306059Samurai#include "lcp.h" 316059Samurai 326059Samuraivoid FsmSendConfigReq(struct fsm *fp); 336059Samuraivoid FsmSendTerminateReq(struct fsm *fp); 346059Samuraivoid FsmInitRestartCounter(struct fsm *fp); 356059Samuraivoid FsmTimeout(struct fsm *fp); 366059Samurai 376059Samuraichar *StateNames[] = { 386059Samurai "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 396059Samurai "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opend", 406059Samurai}; 416059Samurai 426059Samuraivoid 436059SamuraiFsmInit(fp) 446059Samuraistruct fsm *fp; 456059Samurai{ 466059Samurai#ifdef DEBUG 476059Samurai logprintf("FsmInit\n"); 486059Samurai#endif 496059Samurai fp->state = ST_INITIAL; 506059Samurai fp->reqid = 1; 516059Samurai fp->restart = 1; 526059Samurai fp->maxconfig = 3; 536059Samurai} 546059Samurai 556059Samuraivoid 566059SamuraiNewState(fp, new) 576059Samuraistruct fsm *fp; 586059Samuraiint new; 596059Samurai{ 606059Samurai LogPrintf(LOG_LCP, "%s: state change %s --> %s\n", 616059Samurai fp->name, StateNames[fp->state], StateNames[new]); 626059Samurai fp->state = new; 636059Samurai if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) 646059Samurai StopTimer(&fp->FsmTimer); 656059Samurai} 666059Samurai 676059Samuraivoid 686059SamuraiFsmOutput(fp, code, id, ptr, count) 696059Samuraistruct fsm *fp; 706059Samuraiu_int code, id; 716059Samuraiu_char *ptr; 726059Samuraiint count; 736059Samurai{ 746059Samurai int plen; 756059Samurai struct fsmheader lh; 766059Samurai struct mbuf *bp; 776059Samurai 786059Samurai plen = sizeof(struct fsmheader) + count; 796059Samurai lh.code = code; 806059Samurai lh.id = id; 816059Samurai lh.length = htons(plen); 826059Samurai bp = mballoc(plen, MB_FSM); 836059Samurai bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); 846059Samurai if (count) 856059Samurai bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); 866059Samurai#ifdef DEBUG 876059Samurai DumpBp(bp); 886059Samurai#endif 896059Samurai HdlcOutput(PRI_NORMAL, fp->proto, bp); 906059Samurai} 916059Samurai 926059Samuraivoid 936059SamuraiFsmOpen(fp) 946059Samuraistruct fsm *fp; 956059Samurai{ 966059Samurai switch (fp->state) { 976059Samurai case ST_INITIAL: 986059Samurai (fp->LayerStart)(fp); 996059Samurai NewState(fp, ST_STARTING); 1006059Samurai break; 1016059Samurai case ST_STARTING: 1026059Samurai break; 1036059Samurai case ST_CLOSED: 1046059Samurai if (fp->open_mode == OPEN_PASSIVE) { 1056059Samurai NewState(fp, ST_STOPPED); 1066059Samurai } else { 1076059Samurai FsmInitRestartCounter(fp); 1086059Samurai FsmSendConfigReq(fp); 1096059Samurai NewState(fp, ST_REQSENT); 1106059Samurai } 1116059Samurai break; 1126059Samurai case ST_STOPPED: /* XXX: restart option */ 1136059Samurai case ST_REQSENT: 1146059Samurai case ST_ACKRCVD: 1156059Samurai case ST_ACKSENT: 1166059Samurai case ST_OPENED: /* XXX: restart option */ 1176059Samurai break; 1186059Samurai case ST_CLOSING: /* XXX: restart option */ 1196059Samurai case ST_STOPPING: /* XXX: restart option */ 1206059Samurai NewState(fp, ST_STOPPING); 1216059Samurai break; 1226059Samurai } 1236059Samurai} 1246059Samurai 1256059Samuraivoid 1266059SamuraiFsmUp(fp) 1276059Samuraistruct fsm *fp; 1286059Samurai{ 1296059Samurai switch (fp->state) { 1306059Samurai case ST_INITIAL: 1316059Samurai NewState(fp, ST_CLOSED); 1326059Samurai break; 1336059Samurai case ST_STARTING: 1346059Samurai FsmInitRestartCounter(fp); 1356059Samurai FsmSendConfigReq(fp); 1366059Samurai NewState(fp, ST_REQSENT); 1376059Samurai break; 1386059Samurai default: 1396059Samurai LogPrintf(LOG_LCP, "%s: Oops, Up at %s\n", 1406059Samurai fp->name, StateNames[fp->state]); 1416059Samurai break; 1426059Samurai } 1436059Samurai} 1446059Samurai 1456059Samuraivoid 1466059SamuraiFsmDown(fp) 1476059Samuraistruct fsm *fp; 1486059Samurai{ 1496059Samurai switch (fp->state) { 1506059Samurai case ST_CLOSED: 1516059Samurai case ST_CLOSING: 1526059Samurai NewState(fp, ST_INITIAL); 1536059Samurai break; 1546059Samurai case ST_STOPPED: 1556059Samurai (fp->LayerStart)(fp); 1566059Samurai /* Fall into.. */ 1576059Samurai case ST_STOPPING: 1586059Samurai case ST_REQSENT: 1596059Samurai case ST_ACKRCVD: 1606059Samurai case ST_ACKSENT: 1616059Samurai NewState(fp, ST_STARTING); 1626059Samurai break; 1636059Samurai case ST_OPENED: 1646059Samurai (fp->LayerDown)(fp); 1656059Samurai NewState(fp, ST_STARTING); 1666059Samurai break; 1676059Samurai } 1686059Samurai} 1696059Samurai 1706059Samuraivoid 1716059SamuraiFsmClose(fp) 1726059Samuraistruct fsm *fp; 1736059Samurai{ 1746059Samurai switch (fp->state) { 1756059Samurai case ST_STARTING: 1766059Samurai NewState(fp, ST_INITIAL); 1776059Samurai break; 1786059Samurai case ST_STOPPED: 1796059Samurai NewState(fp, ST_CLOSED); 1806059Samurai break; 1816059Samurai case ST_STOPPING: 1826059Samurai NewState(fp, ST_CLOSING); 1836059Samurai break; 1846059Samurai case ST_OPENED: 1856059Samurai (fp->LayerDown)(fp); 1866059Samurai /* Fall down */ 1876059Samurai case ST_REQSENT: 1886059Samurai case ST_ACKRCVD: 1896059Samurai case ST_ACKSENT: 1906059Samurai FsmInitRestartCounter(fp); 1916059Samurai FsmSendTerminateReq(fp); 1926059Samurai NewState(fp, ST_CLOSING); 1936059Samurai break; 1946059Samurai } 1956059Samurai} 1966059Samurai 1976059Samurai/* 1986059Samurai * Send functions 1996059Samurai */ 2006059Samuraivoid 2016059SamuraiFsmSendConfigReq(fp) 2026059Samuraistruct fsm *fp; 2036059Samurai{ 2046059Samurai if (--fp->maxconfig > 0) { 2056059Samurai (fp->SendConfigReq)(fp); 2066059Samurai StartTimer(&fp->FsmTimer); /* Start restart timer */ 2076059Samurai fp->restart--; /* Decrement restart counter */ 2086059Samurai } else { 2096059Samurai FsmClose(fp); 2106059Samurai } 2116059Samurai} 2126059Samurai 2136059Samuraivoid 2146059SamuraiFsmSendTerminateReq(fp) 2156059Samuraistruct fsm *fp; 2166059Samurai{ 2176059Samurai LogPrintf(LOG_LCP, "%s: SendTerminateReq.\n", fp->name); 2186059Samurai FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0); 2196059Samurai (fp->SendTerminateReq)(fp); 2206059Samurai StartTimer(&fp->FsmTimer); /* Start restart timer */ 2216059Samurai fp->restart--; /* Decrement restart counter */ 2226059Samurai} 2236059Samurai 2246059Samuraistatic void 2256059SamuraiFsmSendConfigAck(fp, lhp, option, count) 2266059Samuraistruct fsm *fp; 2276059Samuraistruct fsmheader *lhp; 2286059Samuraiu_char *option; 2296059Samuraiint count; 2306059Samurai{ 2316059Samurai LogPrintf(LOG_LCP, "%s: SendConfigAck(%s)\n", fp->name, StateNames[fp->state]); 2326059Samurai FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count); 2336059Samurai} 2346059Samurai 2356059Samuraistatic void 2366059SamuraiFsmSendConfigRej(fp, lhp, option, count) 2376059Samuraistruct fsm *fp; 2386059Samuraistruct fsmheader *lhp; 2396059Samuraiu_char *option; 2406059Samuraiint count; 2416059Samurai{ 2426059Samurai LogPrintf(LOG_LCP, "%s: SendConfigRej(%s)\n", fp->name, StateNames[fp->state]); 2436059Samurai FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count); 2446059Samurai} 2456059Samurai 2466059Samuraistatic void 2476059SamuraiFsmSendConfigNak(fp, lhp, option, count) 2486059Samuraistruct fsm *fp; 2496059Samuraistruct fsmheader *lhp; 2506059Samuraiu_char *option; 2516059Samuraiint count; 2526059Samurai{ 2536059Samurai LogPrintf(LOG_LCP, "%s: SendConfigNak(%s)\n", 2546059Samurai fp->name, StateNames[fp->state]); 2556059Samurai FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count); 2566059Samurai} 2576059Samurai 2586059Samurai/* 2596059Samurai * Timeout actions 2606059Samurai */ 2616059Samuraivoid 2626059SamuraiFsmTimeout(fp) 2636059Samuraistruct fsm *fp; 2646059Samurai{ 2656059Samurai if (fp->restart) { 2666059Samurai switch (fp->state) { 2676059Samurai case ST_CLOSING: 2686059Samurai case ST_STOPPING: 2696059Samurai FsmSendTerminateReq(fp); 2706059Samurai break; 2716059Samurai case ST_REQSENT: 2726059Samurai case ST_ACKSENT: 2736059Samurai FsmSendConfigReq(fp); 2746059Samurai break; 2756059Samurai case ST_ACKRCVD: 2766059Samurai FsmSendConfigReq(fp); 2776059Samurai NewState(fp, ST_REQSENT); 2786059Samurai break; 2796059Samurai } 2806059Samurai StartTimer(&fp->FsmTimer); 2816059Samurai } else { 2826059Samurai switch (fp->state) { 2836059Samurai case ST_CLOSING: 2846059Samurai NewState(fp, ST_CLOSED); 2856059Samurai (fp->LayerFinish)(fp); 2866059Samurai break; 2876059Samurai case ST_STOPPING: 2886059Samurai NewState(fp, ST_STOPPED); 2896059Samurai (fp->LayerFinish)(fp); 2906059Samurai break; 2916059Samurai case ST_REQSENT: /* XXX: 3p */ 2926059Samurai case ST_ACKSENT: 2936059Samurai case ST_ACKRCVD: 2946059Samurai NewState(fp, ST_STOPPED); 2956059Samurai (fp->LayerFinish)(fp); 2966059Samurai break; 2976059Samurai } 2986059Samurai } 2996059Samurai} 3006059Samurai 3016059Samuraivoid 3026059SamuraiFsmInitRestartCounter(fp) 3036059Samuraistruct fsm *fp; 3046059Samurai{ 3056059Samurai StopTimer(&fp->FsmTimer); 3066059Samurai fp->FsmTimer.state = TIMER_STOPPED; 3076059Samurai fp->FsmTimer.func = FsmTimeout; 3086059Samurai fp->FsmTimer.arg = (void *)fp; 3096059Samurai (fp->InitRestartCounter)(fp); 3106059Samurai} 3116059Samurai 3126059Samurai/* 3136059Samurai * Actions when receive packets 3146059Samurai */ 3156059Samuraivoid 3166059SamuraiFsmRecvConfigReq(fp, lhp, bp) /* RCR */ 3176059Samuraistruct fsm *fp; 3186059Samuraistruct fsmheader *lhp; 3196059Samuraistruct mbuf *bp; 3206059Samurai{ 3216059Samurai int plen; 3226059Samurai int ackaction = 0; 3236059Samurai 3246059Samurai plen = plength(bp); 3256059Samurai if (plen < sizeof(struct fsmconfig)) { 3266059Samurailogprintf("** plen = %d\n", plen); 3276059Samurai pfree(bp); 3286059Samurai return; 3296059Samurai } 3306059Samurai 3316059Samurai /* 3326059Samurai * Check and process easy case 3336059Samurai */ 3346059Samurai switch (fp->state) { 3356059Samurai case ST_INITIAL: 3366059Samurai case ST_STARTING: 3376059Samurai LogPrintf(LOG_LCP, "%s: Oops, RCR in %s.\n", 3386059Samurai fp->name, StateNames[fp->state]); 3396059Samurai pfree(bp); 3406059Samurai return; 3416059Samurai case ST_CLOSED: 3426059Samurai (fp->SendTerminateAck)(fp); 3436059Samurai pfree(bp); 3446059Samurai return; 3456059Samurai case ST_CLOSING: 3466059Samurai case ST_STOPPING: 3476059Samurailogprintf("## state = %d\n", fp->state); 3486059Samurai pfree(bp); 3496059Samurai return; 3506059Samurai } 3516059Samurai 3526059Samurai (fp->DecodeConfig)(bp, MODE_REQ); 3536059Samurai 3546059Samurai if (nakp == NakBuff && rejp == RejBuff) 3556059Samurai ackaction = 1; 3566059Samurai 3576059Samurai switch (fp->state) { 3586059Samurai case ST_OPENED: 3596059Samurai (fp->LayerDown)(fp); 3606059Samurai FsmSendConfigReq(fp); 3616059Samurai break; 3626059Samurai case ST_STOPPED: 3636059Samurai FsmInitRestartCounter(fp); 3646059Samurai FsmSendConfigReq(fp); 3656059Samurai break; 3666059Samurai } 3676059Samurai 3686059Samurai if (rejp != RejBuff) 3696059Samurai FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff); 3706059Samurai if (nakp != NakBuff) 3716059Samurai FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff); 3726059Samurai if (ackaction) 3736059Samurai FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff); 3746059Samurai 3756059Samurai switch (fp->state) { 3766059Samurai case ST_STOPPED: 3776059Samurai case ST_OPENED: 3786059Samurai if (ackaction) 3796059Samurai NewState(fp, ST_ACKSENT); 3806059Samurai else 3816059Samurai NewState(fp, ST_REQSENT); 3826059Samurai break; 3836059Samurai case ST_REQSENT: 3846059Samurai if (ackaction) 3856059Samurai NewState(fp, ST_ACKSENT); 3866059Samurai break; 3876059Samurai case ST_ACKRCVD: 3886059Samurai if (ackaction) { 3896059Samurai NewState(fp, ST_OPENED); 3906059Samurai (fp->LayerUp)(fp); 3916059Samurai } 3926059Samurai break; 3936059Samurai case ST_ACKSENT: 3946059Samurai if (!ackaction) 3956059Samurai NewState(fp, ST_REQSENT); 3966059Samurai break; 3976059Samurai } 3986059Samurai pfree(bp); 3996059Samurai} 4006059Samurai 4016059Samuraivoid 4026059SamuraiFsmRecvConfigAck(fp, lhp, bp) /* RCA */ 4036059Samuraistruct fsm *fp; 4046059Samuraistruct fsmheader *lhp; 4056059Samuraistruct mbuf *bp; 4066059Samurai{ 4076059Samurai switch (fp->state) { 4086059Samurai case ST_CLOSED: 4096059Samurai case ST_STOPPED: 4106059Samurai (fp->SendTerminateAck)(fp); 4116059Samurai break; 4126059Samurai case ST_CLOSING: 4136059Samurai case ST_STOPPING: 4146059Samurai break; 4156059Samurai case ST_REQSENT: 4166059Samurai FsmInitRestartCounter(fp); 4176059Samurai NewState(fp, ST_ACKRCVD); 4186059Samurai break; 4196059Samurai case ST_ACKRCVD: 4206059Samurai FsmSendConfigReq(fp); 4216059Samurai NewState(fp, ST_REQSENT); 4226059Samurai break; 4236059Samurai case ST_ACKSENT: 4246059Samurai FsmInitRestartCounter(fp); 4256059Samurai NewState(fp, ST_OPENED); 4266059Samurai (fp->LayerUp)(fp); 4276059Samurai break; 4286059Samurai case ST_OPENED: 4296059Samurai (fp->LayerDown)(fp); 4306059Samurai FsmSendConfigReq(fp); 4316059Samurai NewState(fp, ST_REQSENT); 4326059Samurai break; 4336059Samurai } 4346059Samurai pfree(bp); 4356059Samurai} 4366059Samurai 4376059Samuraivoid 4386059SamuraiFsmRecvConfigNak(fp, lhp, bp) /* RCN */ 4396059Samuraistruct fsm *fp; 4406059Samuraistruct fsmheader *lhp; 4416059Samuraistruct mbuf *bp; 4426059Samurai{ 4436059Samurai int plen; 4446059Samurai 4456059Samurai plen = plength(bp); 4466059Samurai if (plen < sizeof(struct fsmconfig)) { 4476059Samurai pfree(bp); 4486059Samurai return; 4496059Samurai } 4506059Samurai 4516059Samurai /* 4526059Samurai * Check and process easy case 4536059Samurai */ 4546059Samurai switch (fp->state) { 4556059Samurai case ST_INITIAL: 4566059Samurai case ST_STARTING: 4576059Samurai LogPrintf(LOG_LCP, "%s: Oops, RCN in %s.\n", 4586059Samurai fp->name, StateNames[fp->state]); 4596059Samurai pfree(bp); 4606059Samurai return; 4616059Samurai case ST_CLOSED: 4626059Samurai case ST_STOPPED: 4636059Samurai (fp->SendTerminateAck)(fp); 4646059Samurai pfree(bp); 4656059Samurai return; 4666059Samurai case ST_CLOSING: 4676059Samurai case ST_STOPPING: 4686059Samurai pfree(bp); 4696059Samurai return; 4706059Samurai } 4716059Samurai 4726059Samurai (fp->DecodeConfig)(bp, MODE_NAK); 4736059Samurai 4746059Samurai switch (fp->state) { 4756059Samurai case ST_REQSENT: 4766059Samurai case ST_ACKSENT: 4776059Samurai FsmInitRestartCounter(fp); 4786059Samurai FsmSendConfigReq(fp); 4796059Samurai break; 4806059Samurai case ST_OPENED: 4816059Samurai (fp->LayerDown)(fp); 4826059Samurai /* Fall down */ 4836059Samurai case ST_ACKRCVD: 4846059Samurai FsmSendConfigReq(fp); 4856059Samurai NewState(fp, ST_REQSENT); 4866059Samurai break; 4876059Samurai } 4886059Samurai 4896059Samurai pfree(bp); 4906059Samurai} 4916059Samurai 4926059Samuraivoid 4936059SamuraiFsmRecvTermReq(fp, lhp, bp) /* RTR */ 4946059Samuraistruct fsm *fp; 4956059Samuraistruct fsmheader *lhp; 4966059Samuraistruct mbuf *bp; 4976059Samurai{ 4986059Samurai switch (fp->state) { 4996059Samurai case ST_INITIAL: 5006059Samurai case ST_STARTING: 5016059Samurai LogPrintf(LOG_LCP, "%s: Oops, RTR in %s\n", fp->name, 5026059Samurai StateNames[fp->state]); 5036059Samurai break; 5046059Samurai case ST_CLOSED: 5056059Samurai case ST_STOPPED: 5066059Samurai case ST_CLOSING: 5076059Samurai case ST_STOPPING: 5086059Samurai case ST_REQSENT: 5096059Samurai (fp->SendTerminateAck)(fp); 5106059Samurai break; 5116059Samurai case ST_ACKRCVD: 5126059Samurai case ST_ACKSENT: 5136059Samurai (fp->SendTerminateAck)(fp); 5146059Samurai NewState(fp, ST_REQSENT); 5156059Samurai break; 5166059Samurai case ST_OPENED: 5176059Samurai (fp->LayerDown)(fp); 5186059Samurai /* Zero Restart counter */ 5196059Samurai (fp->SendTerminateAck)(fp); 5206059Samurai NewState(fp, ST_STOPPING); 5216059Samurai break; 5226059Samurai } 5236059Samurai pfree(bp); 5246059Samurai} 5256059Samurai 5266059Samuraivoid 5276059SamuraiFsmRecvTermAck(fp, lhp, bp) /* RTA */ 5286059Samuraistruct fsm *fp; 5296059Samuraistruct fsmheader *lhp; 5306059Samuraistruct mbuf *bp; 5316059Samurai{ 5326059Samurai switch (fp->state) { 5336059Samurai case ST_CLOSING: 5346059Samurai NewState(fp, ST_CLOSED); 5356059Samurai (fp->LayerFinish)(fp); 5366059Samurai break; 5376059Samurai case ST_STOPPING: 5386059Samurai NewState(fp, ST_STOPPED); 5396059Samurai (fp->LayerFinish)(fp); 5406059Samurai break; 5416059Samurai case ST_ACKRCVD: 5426059Samurai NewState(fp, ST_REQSENT); 5436059Samurai break; 5446059Samurai case ST_OPENED: 5456059Samurai (fp->LayerDown)(fp); 5466059Samurai FsmSendConfigReq(fp); 5476059Samurai NewState(fp, ST_REQSENT); 5486059Samurai break; 5496059Samurai } 5506059Samurai pfree(bp); 5516059Samurai} 5526059Samurai 5536059Samuraivoid 5546059SamuraiFsmRecvConfigRej(fp, lhp, bp) /* RCJ */ 5556059Samuraistruct fsm *fp; 5566059Samuraistruct fsmheader *lhp; 5576059Samuraistruct mbuf *bp; 5586059Samurai{ 5596059Samurai int plen; 5606059Samurai 5616059Samurai plen = plength(bp); 5626059Samurai if (plen < sizeof(struct fsmconfig)) { 5636059Samurai pfree(bp); 5646059Samurai return; 5656059Samurai } 5666059Samurai LogPrintf(LOG_LCP, "%s: RecvConfigRej.\n", fp->name); 5676059Samurai 5686059Samurai /* 5696059Samurai * Check and process easy case 5706059Samurai */ 5716059Samurai switch (fp->state) { 5726059Samurai case ST_INITIAL: 5736059Samurai case ST_STARTING: 5746059Samurai LogPrintf(LOG_LCP, "%s: Oops, RCJ in %s.\n", 5756059Samurai fp->name, StateNames[fp->state]); 5766059Samurai pfree(bp); 5776059Samurai return; 5786059Samurai case ST_CLOSED: 5796059Samurai case ST_STOPPED: 5806059Samurai (fp->SendTerminateAck)(fp); 5816059Samurai pfree(bp); 5826059Samurai return; 5836059Samurai case ST_CLOSING: 5846059Samurai case ST_STOPPING: 5856059Samurai pfree(bp); 5866059Samurai return; 5876059Samurai } 5886059Samurai 5896059Samurai (fp->DecodeConfig)(bp, MODE_REJ); 5906059Samurai 5916059Samurai switch (fp->state) { 5926059Samurai case ST_REQSENT: 5936059Samurai case ST_ACKSENT: 5946059Samurai FsmInitRestartCounter(fp); 5956059Samurai FsmSendConfigReq(fp); 5966059Samurai break; 5976059Samurai case ST_OPENED: 5986059Samurai (fp->LayerDown)(fp); 5996059Samurai /* Fall down */ 6006059Samurai case ST_ACKRCVD: 6016059Samurai FsmSendConfigReq(fp); 6026059Samurai NewState(fp, ST_REQSENT); 6036059Samurai break; 6046059Samurai } 6056059Samurai pfree(bp); 6066059Samurai} 6076059Samurai 6086059Samuraivoid 6096059SamuraiFsmRecvCodeRej(fp, lhp, bp) 6106059Samuraistruct fsm *fp; 6116059Samuraistruct fsmheader *lhp; 6126059Samuraistruct mbuf *bp; 6136059Samurai{ 6146059Samurai LogPrintf(LOG_LCP, "%s: RecvCodeRej\n", fp->name); 6156059Samurai pfree(bp); 6166059Samurai} 6176059Samurai 6186059Samuraivoid 6196059SamuraiFsmRecvProtoRej(fp, lhp, bp) 6206059Samuraistruct fsm *fp; 6216059Samuraistruct fsmheader *lhp; 6226059Samuraistruct mbuf *bp; 6236059Samurai{ 6246059Samurai u_short *sp, proto; 6256059Samurai 6266059Samurai sp = (u_short *)MBUF_CTOP(bp); 6276059Samurai proto = ntohs(*sp); 6286059Samurai LogPrintf(LOG_LCP, "-- Protocol (%04x) was rejected.\n", proto); 6296059Samurai 6306059Samurai switch (proto) { 6316059Samurai case PROTO_LQR: 6326059Samurai StopLqr(LQM_LQR); 6336059Samurai break; 6346059Samurai case PROTO_CCP: 6356059Samurai fp = &CcpFsm; 6366059Samurai (fp->LayerFinish)(fp); 6376059Samurai switch (fp->state) { 6386059Samurai case ST_CLOSED: 6396059Samurai case ST_CLOSING: 6406059Samurai NewState(fp, ST_CLOSED); 6416059Samurai default: 6426059Samurai NewState(fp, ST_STOPPED); 6436059Samurai break; 6446059Samurai } 6456059Samurai break; 6466059Samurai } 6476059Samurai pfree(bp); 6486059Samurai} 6496059Samurai 6506059Samuraivoid 6516059SamuraiFsmRecvEchoReq(fp, lhp, bp) 6526059Samuraistruct fsm *fp; 6536059Samuraistruct fsmheader *lhp; 6546059Samuraistruct mbuf *bp; 6556059Samurai{ 6566059Samurai u_char *cp; 6576059Samurai u_long *lp, magic; 6586059Samurai 6596059Samurai cp = MBUF_CTOP(bp); 6606059Samurai lp = (u_long *)cp; 6616059Samurai magic = ntohl(*lp); 6626059Samurai if (magic != LcpInfo.his_magic) { 6636059Samurai logprintf("RecvEchoReq: his magic is bad!!\n"); 6646059Samurai /* XXX: We should send terminate request */ 6656059Samurai } 6666059Samurai 6676059Samurai if (fp->state == ST_OPENED) { 6686059Samurai *lp = htonl(LcpInfo.want_magic); /* Insert local magic number */ 6696059Samurai LogPrintf(LOG_LCP, "%s: SendEchoRep(%s)\n", fp->name, StateNames[fp->state]); 6706059Samurai FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp)); 6716059Samurai } 6726059Samurai pfree(bp); 6736059Samurai} 6746059Samurai 6756059Samuraivoid 6766059SamuraiFsmRecvEchoRep(fp, lhp, bp) 6776059Samuraistruct fsm *fp; 6786059Samuraistruct fsmheader *lhp; 6796059Samuraistruct mbuf *bp; 6806059Samurai{ 6816059Samurai u_long *lp, magic; 6826059Samurai 6836059Samurai lp = (u_long *)MBUF_CTOP(bp); 6846059Samurai magic = ntohl(*lp); 6856059Samurai if (magic != 0 && magic != LcpInfo.his_magic) { 6866059Samurai logprintf("RecvEchoRep: his magic is wrong! expect: %x got: %x\n", 6876059Samurai LcpInfo.his_magic, magic); 6886059Samurai /* 6896059Samurai * XXX: We should send terminate request. But poor implementation 6906059Samurai * may die as a result. 6916059Samurai */ 6926059Samurai } 6936059Samurai RecvEchoLqr(bp); 6946059Samurai pfree(bp); 6956059Samurai} 6966059Samurai 6976059Samuraivoid 6986059SamuraiFsmRecvDiscReq(fp, lhp, bp) 6996059Samuraistruct fsm *fp; 7006059Samuraistruct fsmheader *lhp; 7016059Samuraistruct mbuf *bp; 7026059Samurai{ 7036059Samurai LogPrintf(LOG_LCP, "%s: RecvDiscReq\n", fp->name); 7046059Samurai pfree(bp); 7056059Samurai} 7066059Samurai 7076059Samuraivoid 7086059SamuraiFsmRecvIdent(fp, lhp, bp) 7096059Samuraistruct fsm *fp; 7106059Samuraistruct fsmheader *lhp; 7116059Samuraistruct mbuf *bp; 7126059Samurai{ 7136059Samurai LogPrintf(LOG_LCP, "%s: RecvIdent\n", fp->name); 7146059Samurai pfree(bp); 7156059Samurai} 7166059Samurai 7176059Samuraivoid 7186059SamuraiFsmRecvTimeRemain(fp, lhp, bp) 7196059Samuraistruct fsm *fp; 7206059Samuraistruct fsmheader *lhp; 7216059Samuraistruct mbuf *bp; 7226059Samurai{ 7236059Samurai LogPrintf(LOG_LCP, "%s: RecvTimeRemain\n", fp->name); 7246059Samurai pfree(bp); 7256059Samurai} 7266059Samurai 7276059Samuraivoid 7286059SamuraiFsmRecvResetReq(fp, lhp, bp) 7296059Samuraistruct fsm *fp; 7306059Samuraistruct fsmheader *lhp; 7316059Samuraistruct mbuf *bp; 7326059Samurai{ 7336059Samurai LogPrintf(LOG_LCP, "%s: RecvResetReq\n", fp->name); 7346059Samurai CcpRecvResetReq(fp); 7356059Samurai LogPrintf(LOG_LCP, "%s: SendResetAck\n", fp->name); 7366059Samurai FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0); 7376059Samurai pfree(bp); 7386059Samurai} 7396059Samurai 7406059Samuraivoid 7416059SamuraiFsmRecvResetAck(fp, lhp, bp) 7426059Samuraistruct fsm *fp; 7436059Samuraistruct fsmheader *lhp; 7446059Samuraistruct mbuf *bp; 7456059Samurai{ 7466059Samurai LogPrintf(LOG_LCP, "%s: RecvResetAck\n", fp->name); 7476059Samurai fp->reqid++; 7486059Samurai pfree(bp); 7496059Samurai} 7506059Samurai 7516059Samuraistruct fsmcodedesc FsmCodes[] = { 7526059Samurai { FsmRecvConfigReq, "Configure Request", }, 7536059Samurai { FsmRecvConfigAck, "Configure Ack", }, 7546059Samurai { FsmRecvConfigNak, "Configure Nak", }, 7556059Samurai { FsmRecvConfigRej, "Configure Reject", }, 7566059Samurai { FsmRecvTermReq, "Terminate Request", }, 7576059Samurai { FsmRecvTermAck, "Terminate Ack", }, 7586059Samurai { FsmRecvCodeRej, "Code Reject", }, 7596059Samurai { FsmRecvProtoRej, "Protocol Reject", }, 7606059Samurai { FsmRecvEchoReq, "Echo Request", }, 7616059Samurai { FsmRecvEchoRep, "Echo Reply", }, 7626059Samurai { FsmRecvDiscReq, "Discard Request", }, 7636059Samurai { FsmRecvIdent, "Ident", }, 7646059Samurai { FsmRecvTimeRemain, "Time Remain", }, 7656059Samurai { FsmRecvResetReq, "Reset Request", }, 7666059Samurai { FsmRecvResetAck, "Reset Ack", }, 7676059Samurai}; 7686059Samurai 7696059Samuraivoid 7706059SamuraiFsmInput(fp, bp) 7716059Samuraistruct fsm *fp; 7726059Samuraistruct mbuf *bp; 7736059Samurai{ 7746059Samurai int len; 7756059Samurai struct fsmheader *lhp; 7766059Samurai struct fsmcodedesc *codep; 7776059Samurai 7786059Samurai len = plength(bp); 7796059Samurai if (len < sizeof(struct fsmheader)) { 7806059Samurai pfree(bp); 7816059Samurai return; 7826059Samurai } 7836059Samurai lhp = (struct fsmheader *)MBUF_CTOP(bp); 7846059Samurai if (lhp->code == 0 || lhp->code > fp->max_code) { 7856059Samurai pfree(bp); /* XXX: Should send code reject */ 7866059Samurai return; 7876059Samurai } 7886059Samurai 7896059Samurai bp->offset += sizeof(struct fsmheader); 7906059Samurai bp->cnt -= sizeof(struct fsmheader); 7916059Samurai 7926059Samurai codep = FsmCodes + lhp->code - 1; 7936059Samurai LogPrintf(LOG_LCP, "%s: Received %s (%d) state = %s (%d)\n", 7946059Samurai fp->name, codep->name, lhp->code, StateNames[fp->state], fp->state); 7956059Samurai#ifdef DEBUG 7966059Samurai LogMemory(); 7976059Samurai#endif 7986059Samurai (codep->action)(fp, lhp, bp); 7996059Samurai#ifdef DEBUG 8006059Samurai LogMemory(); 8016059Samurai#endif 8026059Samurai} 803