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 * 201e991daaSBrian Somers * $Id: fsm.c,v 1.27.2.23 1998/03/20 19:46:43 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> 28eaa4df37SBrian Somers #include <netinet/in_systm.h> 29eaa4df37SBrian Somers #include <netinet/ip.h> 301ae349f5Scvs2svn 311ae349f5Scvs2svn #include <stdio.h> 321ae349f5Scvs2svn #include <string.h> 331ae349f5Scvs2svn #include <termios.h> 341ae349f5Scvs2svn 351ae349f5Scvs2svn #include "command.h" 361ae349f5Scvs2svn #include "mbuf.h" 371ae349f5Scvs2svn #include "log.h" 381ae349f5Scvs2svn #include "defs.h" 391ae349f5Scvs2svn #include "timer.h" 401ae349f5Scvs2svn #include "fsm.h" 411ae349f5Scvs2svn #include "lqr.h" 42879ed6faSBrian Somers #include "hdlc.h" 431ae349f5Scvs2svn #include "lcpproto.h" 441ae349f5Scvs2svn #include "lcp.h" 451ae349f5Scvs2svn #include "ccp.h" 461ae349f5Scvs2svn #include "modem.h" 471ae349f5Scvs2svn #include "loadalias.h" 481ae349f5Scvs2svn #include "vars.h" 498c07a7b2SBrian Somers #include "throughput.h" 506140ba11SBrian Somers #include "async.h" 518c07a7b2SBrian Somers #include "link.h" 5242d4d396SBrian Somers #include "descriptor.h" 5363b73463SBrian Somers #include "physical.h" 545828db6dSBrian Somers #include "iplist.h" 55eaa4df37SBrian Somers #include "slcompress.h" 565828db6dSBrian Somers #include "ipcp.h" 575ca5389aSBrian Somers #include "filter.h" 5883d1af55SBrian Somers #include "bundle.h" 59dc0fdb6bSBrian Somers #include "auth.h" 60dc0fdb6bSBrian Somers #include "chat.h" 61dc0fdb6bSBrian Somers #include "chap.h" 62dc0fdb6bSBrian Somers #include "pap.h" 63dc0fdb6bSBrian Somers #include "datalink.h" 641ae349f5Scvs2svn 651ae349f5Scvs2svn static void FsmSendConfigReq(struct fsm *); 661ae349f5Scvs2svn static void FsmSendTerminateReq(struct fsm *); 671ae349f5Scvs2svn static void FsmInitRestartCounter(struct fsm *); 681ae349f5Scvs2svn 692267893fSBrian Somers typedef void (recvfn)(struct fsm *, struct fsmheader *, struct mbuf *); 702267893fSBrian Somers static recvfn FsmRecvConfigReq, FsmRecvConfigAck, FsmRecvConfigNak, 712267893fSBrian Somers FsmRecvConfigRej, FsmRecvTermReq, FsmRecvTermAck, 722267893fSBrian Somers FsmRecvCodeRej, FsmRecvProtoRej, FsmRecvEchoReq, 732267893fSBrian Somers FsmRecvEchoRep, FsmRecvDiscReq, FsmRecvIdent, 742267893fSBrian Somers FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck; 752267893fSBrian Somers 762267893fSBrian Somers static const struct fsmcodedesc { 772267893fSBrian Somers recvfn *recv; 782267893fSBrian Somers unsigned check_reqid : 1; 792267893fSBrian Somers unsigned inc_reqid : 1; 802267893fSBrian Somers const char *name; 812267893fSBrian Somers } FsmCodes[] = { 822267893fSBrian Somers { FsmRecvConfigReq, 0, 0, "ConfigReq" }, 832267893fSBrian Somers { FsmRecvConfigAck, 1, 1, "ConfigAck" }, 842267893fSBrian Somers { FsmRecvConfigNak, 1, 1, "ConfigNak" }, 852267893fSBrian Somers { FsmRecvConfigRej, 1, 1, "ConfigRej" }, 862267893fSBrian Somers { FsmRecvTermReq, 0, 0, "TerminateReq" }, 872267893fSBrian Somers { FsmRecvTermAck, 1, 1, "TerminateAck" }, 882267893fSBrian Somers { FsmRecvCodeRej, 0, 0, "CodeRej" }, 892267893fSBrian Somers { FsmRecvProtoRej, 0, 0, "ProtocolRej" }, 902267893fSBrian Somers { FsmRecvEchoReq, 0, 0, "EchoRequest" }, 912267893fSBrian Somers { FsmRecvEchoRep, 0, 0, "EchoReply" }, 922267893fSBrian Somers { FsmRecvDiscReq, 0, 0, "DiscardReq" }, 932267893fSBrian Somers { FsmRecvIdent, 0, 0, "Ident" }, 942267893fSBrian Somers { FsmRecvTimeRemain,0, 0, "TimeRemain" }, 952267893fSBrian Somers { FsmRecvResetReq, 0, 0, "ResetReqt" }, 962267893fSBrian Somers { FsmRecvResetAck, 0, 1, "ResetAck" } 972267893fSBrian Somers }; 982267893fSBrian Somers 992267893fSBrian Somers static const char * 1002267893fSBrian Somers Code2Nam(u_int code) 1012267893fSBrian Somers { 1022267893fSBrian Somers if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0]) 1032267893fSBrian Somers return "Unknown"; 1042267893fSBrian Somers return FsmCodes[code-1].name; 1052267893fSBrian Somers } 1062267893fSBrian Somers 1071e991daaSBrian Somers const char * 1081e991daaSBrian Somers State2Nam(u_int state) 1091e991daaSBrian Somers { 1101e991daaSBrian Somers static const char *StateNames[] = { 1111e991daaSBrian Somers "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 1121e991daaSBrian Somers "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened", 1131e991daaSBrian Somers }; 1141e991daaSBrian Somers 1151e991daaSBrian Somers if (state >= sizeof StateNames / sizeof StateNames[0]) 1161e991daaSBrian Somers return "unknown"; 1171e991daaSBrian Somers return StateNames[state]; 1181e991daaSBrian Somers } 1191e991daaSBrian Somers 1201ae349f5Scvs2svn static void 1211ae349f5Scvs2svn StoppedTimeout(void *v) 1221ae349f5Scvs2svn { 1231ae349f5Scvs2svn struct fsm *fp = (struct fsm *)v; 1241ae349f5Scvs2svn 1251ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Stopped timer expired\n"); 1261ae349f5Scvs2svn if (fp->OpenTimer.state == TIMER_RUNNING) { 1271ae349f5Scvs2svn LogPrintf(LogWARN, "%s: aborting open delay due to stopped timer\n", 1281ae349f5Scvs2svn fp->name); 1291ae349f5Scvs2svn StopTimer(&fp->OpenTimer); 1301ae349f5Scvs2svn } 1318c07a7b2SBrian Somers if (link_IsActive(fp->link)) 1323006ec67SBrian Somers link_Close(fp->link, fp->bundle, 0, 1); 1331ae349f5Scvs2svn } 1341ae349f5Scvs2svn 1351ae349f5Scvs2svn void 136503a7782SBrian Somers fsm_Init(struct fsm *fp, const char *name, u_short proto, int maxcode, 137503a7782SBrian Somers int maxcfg, int LogLevel, struct bundle *bundle, struct link *l, 1386d666775SBrian Somers const struct fsm_parent *parent, struct fsm_callbacks *fn) 1391ae349f5Scvs2svn { 140503a7782SBrian Somers fp->name = name; 141503a7782SBrian Somers fp->proto = proto; 142503a7782SBrian Somers fp->max_code = maxcode; 1431ae349f5Scvs2svn fp->state = ST_INITIAL; 1441ae349f5Scvs2svn fp->reqid = 1; 1451ae349f5Scvs2svn fp->restart = 1; 146503a7782SBrian Somers fp->maxconfig = maxcfg; 147503a7782SBrian Somers memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer); 148503a7782SBrian Somers memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer); 149503a7782SBrian Somers memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer); 150503a7782SBrian Somers fp->LogLevel = LogLevel; 1518c07a7b2SBrian Somers fp->link = l; 1527a6f8720SBrian Somers fp->bundle = bundle; 1536d666775SBrian Somers fp->parent = parent; 154503a7782SBrian Somers fp->fn = fn; 1551ae349f5Scvs2svn } 1561ae349f5Scvs2svn 1571ae349f5Scvs2svn static void 1581ae349f5Scvs2svn NewState(struct fsm * fp, int new) 1591ae349f5Scvs2svn { 1601ae349f5Scvs2svn LogPrintf(fp->LogLevel, "State change %s --> %s\n", 1611e991daaSBrian Somers State2Nam(fp->state), State2Nam(new)); 1621ae349f5Scvs2svn if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING) 1631ae349f5Scvs2svn StopTimer(&fp->StoppedTimer); 1641ae349f5Scvs2svn fp->state = new; 1651ae349f5Scvs2svn if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) { 1661ae349f5Scvs2svn StopTimer(&fp->FsmTimer); 1671ae349f5Scvs2svn if (new == ST_STOPPED && fp->StoppedTimer.load) { 1681ae349f5Scvs2svn fp->StoppedTimer.state = TIMER_STOPPED; 1691ae349f5Scvs2svn fp->StoppedTimer.func = StoppedTimeout; 1701ae349f5Scvs2svn fp->StoppedTimer.arg = (void *) fp; 1711ae349f5Scvs2svn StartTimer(&fp->StoppedTimer); 1721ae349f5Scvs2svn } 1731ae349f5Scvs2svn } 1741ae349f5Scvs2svn } 1751ae349f5Scvs2svn 1761ae349f5Scvs2svn void 1771ae349f5Scvs2svn FsmOutput(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count) 1781ae349f5Scvs2svn { 1791ae349f5Scvs2svn int plen; 1801ae349f5Scvs2svn struct fsmheader lh; 1811ae349f5Scvs2svn struct mbuf *bp; 1821ae349f5Scvs2svn 1832267893fSBrian Somers if (LogIsKept(fp->LogLevel)) { 1842267893fSBrian Somers LogPrintf(fp->LogLevel, "Send%s(%d) state = %s\n", Code2Nam(code), 1851e991daaSBrian Somers id, State2Nam(fp->state)); 1862267893fSBrian Somers switch (code) { 1872267893fSBrian Somers case CODE_CONFIGREQ: 1882267893fSBrian Somers case CODE_CONFIGACK: 1892267893fSBrian Somers case CODE_CONFIGREJ: 1902267893fSBrian Somers case CODE_CONFIGNAK: 1912267893fSBrian Somers (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL); 1922267893fSBrian Somers if (count < sizeof(struct fsmconfig)) 1932267893fSBrian Somers LogPrintf(fp->LogLevel, " [EMPTY]\n"); 1942267893fSBrian Somers break; 1952267893fSBrian Somers } 1962267893fSBrian Somers } 1972267893fSBrian Somers 1981ae349f5Scvs2svn plen = sizeof(struct fsmheader) + count; 1991ae349f5Scvs2svn lh.code = code; 2001ae349f5Scvs2svn lh.id = id; 2011ae349f5Scvs2svn lh.length = htons(plen); 2021ae349f5Scvs2svn bp = mballoc(plen, MB_FSM); 2031ae349f5Scvs2svn memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 2041ae349f5Scvs2svn if (count) 2051ae349f5Scvs2svn memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count); 2061ae349f5Scvs2svn LogDumpBp(LogDEBUG, "FsmOutput", bp); 2078c07a7b2SBrian Somers HdlcOutput(fp->link, PRI_LINK, fp->proto, bp); 2081ae349f5Scvs2svn } 2091ae349f5Scvs2svn 2101ae349f5Scvs2svn static void 2111ae349f5Scvs2svn FsmOpenNow(void *v) 2121ae349f5Scvs2svn { 2131ae349f5Scvs2svn struct fsm *fp = (struct fsm *)v; 2141ae349f5Scvs2svn 2151ae349f5Scvs2svn StopTimer(&fp->OpenTimer); 2161ae349f5Scvs2svn if (fp->state <= ST_STOPPED) { 2171ae349f5Scvs2svn FsmInitRestartCounter(fp); 2181ae349f5Scvs2svn FsmSendConfigReq(fp); 2191ae349f5Scvs2svn NewState(fp, ST_REQSENT); 2201ae349f5Scvs2svn } 2211ae349f5Scvs2svn } 2221ae349f5Scvs2svn 2231ae349f5Scvs2svn void 2241ae349f5Scvs2svn FsmOpen(struct fsm * fp) 2251ae349f5Scvs2svn { 2261ae349f5Scvs2svn switch (fp->state) { 2271ae349f5Scvs2svn case ST_INITIAL: 2281ae349f5Scvs2svn NewState(fp, ST_STARTING); 2296d666775SBrian Somers (*fp->fn->LayerStart)(fp); 2306d666775SBrian Somers (*fp->parent->LayerStart)(fp->parent->object, fp); 2311ae349f5Scvs2svn break; 2321ae349f5Scvs2svn case ST_CLOSED: 2331ae349f5Scvs2svn if (fp->open_mode == OPEN_PASSIVE) { 2341ae349f5Scvs2svn NewState(fp, ST_STOPPED); 2351ae349f5Scvs2svn } else if (fp->open_mode > 0) { 2361ae349f5Scvs2svn if (fp->open_mode > 1) 2371ae349f5Scvs2svn LogPrintf(LogPHASE, "Entering STOPPED state for %d seconds\n", 2381ae349f5Scvs2svn fp->open_mode); 2391ae349f5Scvs2svn NewState(fp, ST_STOPPED); 2401ae349f5Scvs2svn fp->OpenTimer.state = TIMER_STOPPED; 2411ae349f5Scvs2svn fp->OpenTimer.load = fp->open_mode * SECTICKS; 2421ae349f5Scvs2svn fp->OpenTimer.func = FsmOpenNow; 2431ae349f5Scvs2svn fp->OpenTimer.arg = (void *)fp; 2441ae349f5Scvs2svn StartTimer(&fp->OpenTimer); 2451ae349f5Scvs2svn } else 2461ae349f5Scvs2svn FsmOpenNow(fp); 2471ae349f5Scvs2svn break; 2481ae349f5Scvs2svn case ST_STOPPED: /* XXX: restart option */ 2491ae349f5Scvs2svn case ST_REQSENT: 2501ae349f5Scvs2svn case ST_ACKRCVD: 2511ae349f5Scvs2svn case ST_ACKSENT: 2521ae349f5Scvs2svn case ST_OPENED: /* XXX: restart option */ 2531ae349f5Scvs2svn break; 2541ae349f5Scvs2svn case ST_CLOSING: /* XXX: restart option */ 2551ae349f5Scvs2svn case ST_STOPPING: /* XXX: restart option */ 2561ae349f5Scvs2svn NewState(fp, ST_STOPPING); 2571ae349f5Scvs2svn break; 2581ae349f5Scvs2svn } 2591ae349f5Scvs2svn } 2601ae349f5Scvs2svn 2611ae349f5Scvs2svn void 2621ae349f5Scvs2svn FsmUp(struct fsm * fp) 2631ae349f5Scvs2svn { 2641ae349f5Scvs2svn switch (fp->state) { 2651ae349f5Scvs2svn case ST_INITIAL: 2661ae349f5Scvs2svn NewState(fp, ST_CLOSED); 2671ae349f5Scvs2svn break; 2681ae349f5Scvs2svn case ST_STARTING: 2691ae349f5Scvs2svn FsmInitRestartCounter(fp); 2701ae349f5Scvs2svn FsmSendConfigReq(fp); 2711ae349f5Scvs2svn NewState(fp, ST_REQSENT); 2721ae349f5Scvs2svn break; 2731ae349f5Scvs2svn default: 2741e991daaSBrian Somers LogPrintf(fp->LogLevel, "Oops, Up at %s\n", State2Nam(fp->state)); 2751ae349f5Scvs2svn break; 2761ae349f5Scvs2svn } 2771ae349f5Scvs2svn } 2781ae349f5Scvs2svn 2791ae349f5Scvs2svn void 2801ae349f5Scvs2svn FsmDown(struct fsm *fp) 2811ae349f5Scvs2svn { 2821ae349f5Scvs2svn switch (fp->state) { 2831ae349f5Scvs2svn case ST_CLOSED: 2841ae349f5Scvs2svn NewState(fp, ST_INITIAL); 2851ae349f5Scvs2svn break; 286455aabc3SBrian Somers case ST_CLOSING: 2876d666775SBrian Somers (*fp->fn->LayerFinish)(fp); 288455aabc3SBrian Somers NewState(fp, ST_INITIAL); 2896d666775SBrian Somers (*fp->parent->LayerFinish)(fp->parent->object, fp); 290455aabc3SBrian Somers break; 2911ae349f5Scvs2svn case ST_STOPPED: 292455aabc3SBrian Somers NewState(fp, ST_STARTING); 2936d666775SBrian Somers (*fp->fn->LayerStart)(fp); 2946d666775SBrian Somers (*fp->parent->LayerStart)(fp->parent->object, fp); 295455aabc3SBrian Somers break; 2961ae349f5Scvs2svn case ST_STOPPING: 2971ae349f5Scvs2svn case ST_REQSENT: 2981ae349f5Scvs2svn case ST_ACKRCVD: 2991ae349f5Scvs2svn case ST_ACKSENT: 3001ae349f5Scvs2svn NewState(fp, ST_STARTING); 3011ae349f5Scvs2svn break; 3021ae349f5Scvs2svn case ST_OPENED: 3036d666775SBrian Somers (*fp->fn->LayerDown)(fp); 3041ae349f5Scvs2svn NewState(fp, ST_STARTING); 3056d666775SBrian Somers (*fp->parent->LayerDown)(fp->parent->object, fp); 3061ae349f5Scvs2svn break; 3071ae349f5Scvs2svn } 3081ae349f5Scvs2svn } 3091ae349f5Scvs2svn 3101ae349f5Scvs2svn void 3111ae349f5Scvs2svn FsmClose(struct fsm *fp) 3121ae349f5Scvs2svn { 3131ae349f5Scvs2svn switch (fp->state) { 3141ae349f5Scvs2svn case ST_STARTING: 3156d666775SBrian Somers (*fp->fn->LayerFinish)(fp); 3161ae349f5Scvs2svn NewState(fp, ST_INITIAL); 3176d666775SBrian Somers (*fp->parent->LayerFinish)(fp->parent->object, fp); 3181ae349f5Scvs2svn break; 3191ae349f5Scvs2svn case ST_STOPPED: 3201ae349f5Scvs2svn NewState(fp, ST_CLOSED); 3211ae349f5Scvs2svn break; 3221ae349f5Scvs2svn case ST_STOPPING: 3231ae349f5Scvs2svn NewState(fp, ST_CLOSING); 3241ae349f5Scvs2svn break; 3251ae349f5Scvs2svn case ST_OPENED: 3266d666775SBrian Somers (*fp->fn->LayerDown)(fp); 327455aabc3SBrian Somers FsmInitRestartCounter(fp); 328455aabc3SBrian Somers FsmSendTerminateReq(fp); 329455aabc3SBrian Somers NewState(fp, ST_CLOSING); 3306d666775SBrian Somers (*fp->parent->LayerDown)(fp->parent->object, fp); 331455aabc3SBrian Somers break; 3321ae349f5Scvs2svn case ST_REQSENT: 3331ae349f5Scvs2svn case ST_ACKRCVD: 3341ae349f5Scvs2svn case ST_ACKSENT: 3351ae349f5Scvs2svn FsmInitRestartCounter(fp); 3361ae349f5Scvs2svn FsmSendTerminateReq(fp); 3371ae349f5Scvs2svn NewState(fp, ST_CLOSING); 3381ae349f5Scvs2svn break; 3391ae349f5Scvs2svn } 3401ae349f5Scvs2svn } 3411ae349f5Scvs2svn 3421ae349f5Scvs2svn /* 3431ae349f5Scvs2svn * Send functions 3441ae349f5Scvs2svn */ 3451ae349f5Scvs2svn static void 3461ae349f5Scvs2svn FsmSendConfigReq(struct fsm * fp) 3471ae349f5Scvs2svn { 3481ae349f5Scvs2svn if (--fp->maxconfig > 0) { 34983d1af55SBrian Somers (*fp->fn->SendConfigReq)(fp); 3501ae349f5Scvs2svn StartTimer(&fp->FsmTimer); /* Start restart timer */ 3511ae349f5Scvs2svn fp->restart--; /* Decrement restart counter */ 3521ae349f5Scvs2svn } else { 3531ae349f5Scvs2svn FsmClose(fp); 3541ae349f5Scvs2svn } 3551ae349f5Scvs2svn } 3561ae349f5Scvs2svn 3571ae349f5Scvs2svn static void 3581ae349f5Scvs2svn FsmSendTerminateReq(struct fsm *fp) 3591ae349f5Scvs2svn { 3602267893fSBrian Somers FsmOutput(fp, CODE_TERMREQ, fp->reqid, NULL, 0); 3612267893fSBrian Somers (*fp->fn->SentTerminateReq)(fp); 3621ae349f5Scvs2svn StartTimer(&fp->FsmTimer); /* Start restart timer */ 3631ae349f5Scvs2svn fp->restart--; /* Decrement restart counter */ 3641ae349f5Scvs2svn } 3651ae349f5Scvs2svn 3661ae349f5Scvs2svn /* 3671ae349f5Scvs2svn * Timeout actions 3681ae349f5Scvs2svn */ 3691ae349f5Scvs2svn static void 3701ae349f5Scvs2svn FsmTimeout(void *v) 3711ae349f5Scvs2svn { 3721ae349f5Scvs2svn struct fsm *fp = (struct fsm *)v; 3731ae349f5Scvs2svn 3741ae349f5Scvs2svn if (fp->restart) { 3751ae349f5Scvs2svn switch (fp->state) { 3761ae349f5Scvs2svn case ST_CLOSING: 3771ae349f5Scvs2svn case ST_STOPPING: 3781ae349f5Scvs2svn FsmSendTerminateReq(fp); 3791ae349f5Scvs2svn break; 3801ae349f5Scvs2svn case ST_REQSENT: 3811ae349f5Scvs2svn case ST_ACKSENT: 3821ae349f5Scvs2svn FsmSendConfigReq(fp); 3831ae349f5Scvs2svn break; 3841ae349f5Scvs2svn case ST_ACKRCVD: 3851ae349f5Scvs2svn FsmSendConfigReq(fp); 3861ae349f5Scvs2svn NewState(fp, ST_REQSENT); 3871ae349f5Scvs2svn break; 3881ae349f5Scvs2svn } 3891ae349f5Scvs2svn StartTimer(&fp->FsmTimer); 3901ae349f5Scvs2svn } else { 3911ae349f5Scvs2svn switch (fp->state) { 3921ae349f5Scvs2svn case ST_CLOSING: 3936d666775SBrian Somers (*fp->fn->LayerFinish)(fp); 394455aabc3SBrian Somers NewState(fp, ST_CLOSED); 3956d666775SBrian Somers (*fp->parent->LayerFinish)(fp->parent->object, fp); 3961ae349f5Scvs2svn break; 3971ae349f5Scvs2svn case ST_STOPPING: 3986d666775SBrian Somers (*fp->fn->LayerFinish)(fp); 399455aabc3SBrian Somers NewState(fp, ST_STOPPED); 4006d666775SBrian Somers (*fp->parent->LayerFinish)(fp->parent->object, fp); 4011ae349f5Scvs2svn break; 4021ae349f5Scvs2svn case ST_REQSENT: /* XXX: 3p */ 4031ae349f5Scvs2svn case ST_ACKSENT: 4041ae349f5Scvs2svn case ST_ACKRCVD: 4056d666775SBrian Somers (*fp->fn->LayerFinish)(fp); 406455aabc3SBrian Somers NewState(fp, ST_STOPPED); 4076d666775SBrian Somers (*fp->parent->LayerFinish)(fp->parent->object, fp); 4081ae349f5Scvs2svn break; 4091ae349f5Scvs2svn } 4101ae349f5Scvs2svn } 4111ae349f5Scvs2svn } 4121ae349f5Scvs2svn 4131ae349f5Scvs2svn static void 4141ae349f5Scvs2svn FsmInitRestartCounter(struct fsm * fp) 4151ae349f5Scvs2svn { 4161ae349f5Scvs2svn StopTimer(&fp->FsmTimer); 4171ae349f5Scvs2svn fp->FsmTimer.state = TIMER_STOPPED; 4181ae349f5Scvs2svn fp->FsmTimer.func = FsmTimeout; 4191ae349f5Scvs2svn fp->FsmTimer.arg = (void *) fp; 42083d1af55SBrian Somers (*fp->fn->InitRestartCounter)(fp); 4211ae349f5Scvs2svn } 4221ae349f5Scvs2svn 4231ae349f5Scvs2svn /* 4241ae349f5Scvs2svn * Actions when receive packets 4251ae349f5Scvs2svn */ 4261ae349f5Scvs2svn static void 4271ae349f5Scvs2svn FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 4281ae349f5Scvs2svn /* RCR */ 4291ae349f5Scvs2svn { 43030c2f2ffSBrian Somers struct fsm_decode dec; 4311ae349f5Scvs2svn int plen, flen; 4321ae349f5Scvs2svn int ackaction = 0; 4331ae349f5Scvs2svn 4341ae349f5Scvs2svn plen = plength(bp); 4351ae349f5Scvs2svn flen = ntohs(lhp->length) - sizeof *lhp; 4361ae349f5Scvs2svn if (plen < flen) { 4371ae349f5Scvs2svn LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)\n", 4381ae349f5Scvs2svn plen, flen); 4391ae349f5Scvs2svn pfree(bp); 4401ae349f5Scvs2svn return; 4411ae349f5Scvs2svn } 4421ae349f5Scvs2svn 4431ae349f5Scvs2svn /* 4441ae349f5Scvs2svn * Check and process easy case 4451ae349f5Scvs2svn */ 4461ae349f5Scvs2svn switch (fp->state) { 4471ae349f5Scvs2svn case ST_INITIAL: 4481ae349f5Scvs2svn case ST_STARTING: 4491e991daaSBrian Somers LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", State2Nam(fp->state)); 4501ae349f5Scvs2svn pfree(bp); 4511ae349f5Scvs2svn return; 4521ae349f5Scvs2svn case ST_CLOSED: 4532267893fSBrian Somers (*fp->fn->SendTerminateAck)(fp, lhp->id); 4541ae349f5Scvs2svn pfree(bp); 4551ae349f5Scvs2svn return; 4561ae349f5Scvs2svn case ST_CLOSING: 4571ae349f5Scvs2svn LogPrintf(fp->LogLevel, "Error: Got ConfigReq while state = %d\n", 4581ae349f5Scvs2svn fp->state); 4591ae349f5Scvs2svn case ST_STOPPING: 4601ae349f5Scvs2svn pfree(bp); 4611ae349f5Scvs2svn return; 4621ae349f5Scvs2svn } 4631ae349f5Scvs2svn 46430c2f2ffSBrian Somers dec.ackend = dec.ack; 46530c2f2ffSBrian Somers dec.nakend = dec.nak; 46630c2f2ffSBrian Somers dec.rejend = dec.rej; 46730c2f2ffSBrian Somers (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec); 4682267893fSBrian Somers if (flen < sizeof(struct fsmconfig)) 4692267893fSBrian Somers LogPrintf(fp->LogLevel, " [EMPTY]\n"); 4701ae349f5Scvs2svn 47130c2f2ffSBrian Somers if (dec.nakend == dec.nak && dec.rejend == dec.rej) 4721ae349f5Scvs2svn ackaction = 1; 4731ae349f5Scvs2svn 4741ae349f5Scvs2svn switch (fp->state) { 4751ae349f5Scvs2svn case ST_OPENED: 4766d666775SBrian Somers (*fp->fn->LayerDown)(fp); 4771ae349f5Scvs2svn FsmSendConfigReq(fp); 4786d666775SBrian Somers (*fp->parent->LayerDown)(fp->parent->object, fp); 4791ae349f5Scvs2svn break; 4801ae349f5Scvs2svn case ST_STOPPED: 4811ae349f5Scvs2svn FsmInitRestartCounter(fp); 4821ae349f5Scvs2svn FsmSendConfigReq(fp); 4831ae349f5Scvs2svn break; 4841ae349f5Scvs2svn } 4851ae349f5Scvs2svn 48630c2f2ffSBrian Somers if (dec.rejend != dec.rej) 4872267893fSBrian Somers FsmOutput(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej); 48830c2f2ffSBrian Somers if (dec.nakend != dec.nak) 4892267893fSBrian Somers FsmOutput(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak); 4901ae349f5Scvs2svn if (ackaction) 4912267893fSBrian Somers FsmOutput(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack); 4921ae349f5Scvs2svn 4931ae349f5Scvs2svn switch (fp->state) { 4941ae349f5Scvs2svn case ST_OPENED: 495455aabc3SBrian Somers case ST_STOPPED: 4961ae349f5Scvs2svn if (ackaction) 4971ae349f5Scvs2svn NewState(fp, ST_ACKSENT); 4981ae349f5Scvs2svn else 4991ae349f5Scvs2svn NewState(fp, ST_REQSENT); 5001ae349f5Scvs2svn break; 5011ae349f5Scvs2svn case ST_REQSENT: 5021ae349f5Scvs2svn if (ackaction) 5031ae349f5Scvs2svn NewState(fp, ST_ACKSENT); 5041ae349f5Scvs2svn break; 5051ae349f5Scvs2svn case ST_ACKRCVD: 5061ae349f5Scvs2svn if (ackaction) { 5071ae349f5Scvs2svn NewState(fp, ST_OPENED); 5086d666775SBrian Somers (*fp->fn->LayerUp)(fp); 5096d666775SBrian Somers (*fp->parent->LayerUp)(fp->parent->object, fp); 5101ae349f5Scvs2svn } 5111ae349f5Scvs2svn break; 5121ae349f5Scvs2svn case ST_ACKSENT: 5131ae349f5Scvs2svn if (!ackaction) 5141ae349f5Scvs2svn NewState(fp, ST_REQSENT); 5151ae349f5Scvs2svn break; 5161ae349f5Scvs2svn } 5171ae349f5Scvs2svn pfree(bp); 5181ae349f5Scvs2svn } 5191ae349f5Scvs2svn 5201ae349f5Scvs2svn static void 5211ae349f5Scvs2svn FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 5221ae349f5Scvs2svn /* RCA */ 5231ae349f5Scvs2svn { 5241ae349f5Scvs2svn switch (fp->state) { 5251ae349f5Scvs2svn case ST_CLOSED: 5261ae349f5Scvs2svn case ST_STOPPED: 5272267893fSBrian Somers (*fp->fn->SendTerminateAck)(fp, lhp->id); 5281ae349f5Scvs2svn break; 5291ae349f5Scvs2svn case ST_CLOSING: 5301ae349f5Scvs2svn case ST_STOPPING: 5311ae349f5Scvs2svn break; 5321ae349f5Scvs2svn case ST_REQSENT: 5331ae349f5Scvs2svn FsmInitRestartCounter(fp); 5341ae349f5Scvs2svn NewState(fp, ST_ACKRCVD); 5351ae349f5Scvs2svn break; 5361ae349f5Scvs2svn case ST_ACKRCVD: 5371ae349f5Scvs2svn FsmSendConfigReq(fp); 5381ae349f5Scvs2svn NewState(fp, ST_REQSENT); 5391ae349f5Scvs2svn break; 5401ae349f5Scvs2svn case ST_ACKSENT: 5411ae349f5Scvs2svn FsmInitRestartCounter(fp); 5421ae349f5Scvs2svn NewState(fp, ST_OPENED); 5436d666775SBrian Somers (*fp->fn->LayerUp)(fp); 5446d666775SBrian Somers (*fp->parent->LayerUp)(fp->parent->object, fp); 5451ae349f5Scvs2svn break; 5461ae349f5Scvs2svn case ST_OPENED: 5476d666775SBrian Somers (*fp->fn->LayerDown)(fp); 5481ae349f5Scvs2svn FsmSendConfigReq(fp); 5491ae349f5Scvs2svn NewState(fp, ST_REQSENT); 5506d666775SBrian Somers (*fp->parent->LayerDown)(fp->parent->object, fp); 5511ae349f5Scvs2svn break; 5521ae349f5Scvs2svn } 5531ae349f5Scvs2svn pfree(bp); 5541ae349f5Scvs2svn } 5551ae349f5Scvs2svn 5561ae349f5Scvs2svn static void 5571ae349f5Scvs2svn FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 5581ae349f5Scvs2svn /* RCN */ 5591ae349f5Scvs2svn { 56030c2f2ffSBrian Somers struct fsm_decode dec; 5611ae349f5Scvs2svn int plen, flen; 5621ae349f5Scvs2svn 5631ae349f5Scvs2svn plen = plength(bp); 5641ae349f5Scvs2svn flen = ntohs(lhp->length) - sizeof *lhp; 5651ae349f5Scvs2svn if (plen < flen) { 5661ae349f5Scvs2svn pfree(bp); 5671ae349f5Scvs2svn return; 5681ae349f5Scvs2svn } 5691ae349f5Scvs2svn 5701ae349f5Scvs2svn /* 5711ae349f5Scvs2svn * Check and process easy case 5721ae349f5Scvs2svn */ 5731ae349f5Scvs2svn switch (fp->state) { 5741ae349f5Scvs2svn case ST_INITIAL: 5751ae349f5Scvs2svn case ST_STARTING: 5761e991daaSBrian Somers LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", State2Nam(fp->state)); 5771ae349f5Scvs2svn pfree(bp); 5781ae349f5Scvs2svn return; 5791ae349f5Scvs2svn case ST_CLOSED: 5801ae349f5Scvs2svn case ST_STOPPED: 5812267893fSBrian Somers (*fp->fn->SendTerminateAck)(fp, lhp->id); 5821ae349f5Scvs2svn pfree(bp); 5831ae349f5Scvs2svn return; 5841ae349f5Scvs2svn case ST_CLOSING: 5851ae349f5Scvs2svn case ST_STOPPING: 5861ae349f5Scvs2svn pfree(bp); 5871ae349f5Scvs2svn return; 5881ae349f5Scvs2svn } 5891ae349f5Scvs2svn 59030c2f2ffSBrian Somers dec.ackend = dec.ack; 59130c2f2ffSBrian Somers dec.nakend = dec.nak; 59230c2f2ffSBrian Somers dec.rejend = dec.rej; 59330c2f2ffSBrian Somers (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec); 5942267893fSBrian Somers if (flen < sizeof(struct fsmconfig)) 5952267893fSBrian Somers LogPrintf(fp->LogLevel, " [EMPTY]\n"); 5961ae349f5Scvs2svn 5971ae349f5Scvs2svn switch (fp->state) { 5981ae349f5Scvs2svn case ST_REQSENT: 5991ae349f5Scvs2svn case ST_ACKSENT: 6001ae349f5Scvs2svn FsmInitRestartCounter(fp); 6011ae349f5Scvs2svn FsmSendConfigReq(fp); 6021ae349f5Scvs2svn break; 6031ae349f5Scvs2svn case ST_OPENED: 6046d666775SBrian Somers (*fp->fn->LayerDown)(fp); 605455aabc3SBrian Somers FsmSendConfigReq(fp); 606455aabc3SBrian Somers NewState(fp, ST_REQSENT); 6076d666775SBrian Somers (*fp->parent->LayerDown)(fp->parent->object, fp); 608455aabc3SBrian Somers break; 6091ae349f5Scvs2svn case ST_ACKRCVD: 6101ae349f5Scvs2svn FsmSendConfigReq(fp); 6111ae349f5Scvs2svn NewState(fp, ST_REQSENT); 6121ae349f5Scvs2svn break; 6131ae349f5Scvs2svn } 6141ae349f5Scvs2svn 6151ae349f5Scvs2svn pfree(bp); 6161ae349f5Scvs2svn } 6171ae349f5Scvs2svn 6181ae349f5Scvs2svn static void 6191ae349f5Scvs2svn FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 6201ae349f5Scvs2svn /* RTR */ 6211ae349f5Scvs2svn { 6221ae349f5Scvs2svn switch (fp->state) { 6231ae349f5Scvs2svn case ST_INITIAL: 6241ae349f5Scvs2svn case ST_STARTING: 6251e991daaSBrian Somers LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", State2Nam(fp->state)); 6261ae349f5Scvs2svn break; 6271ae349f5Scvs2svn case ST_CLOSED: 6281ae349f5Scvs2svn case ST_STOPPED: 6291ae349f5Scvs2svn case ST_CLOSING: 6301ae349f5Scvs2svn case ST_STOPPING: 6311ae349f5Scvs2svn case ST_REQSENT: 6322267893fSBrian Somers (*fp->fn->SendTerminateAck)(fp, lhp->id); 6331ae349f5Scvs2svn break; 6341ae349f5Scvs2svn case ST_ACKRCVD: 6351ae349f5Scvs2svn case ST_ACKSENT: 6362267893fSBrian Somers (*fp->fn->SendTerminateAck)(fp, lhp->id); 6371ae349f5Scvs2svn NewState(fp, ST_REQSENT); 6381ae349f5Scvs2svn break; 6391ae349f5Scvs2svn case ST_OPENED: 6406d666775SBrian Somers (*fp->fn->LayerDown)(fp); 6412267893fSBrian Somers (*fp->fn->SendTerminateAck)(fp, lhp->id); 6421ae349f5Scvs2svn StartTimer(&fp->FsmTimer); /* Start restart timer */ 6431ae349f5Scvs2svn fp->restart = 0; 6441ae349f5Scvs2svn NewState(fp, ST_STOPPING); 6456d666775SBrian Somers (*fp->parent->LayerDown)(fp->parent->object, fp); 6461ae349f5Scvs2svn break; 6471ae349f5Scvs2svn } 6481ae349f5Scvs2svn pfree(bp); 6491ae349f5Scvs2svn } 6501ae349f5Scvs2svn 6511ae349f5Scvs2svn static void 6521ae349f5Scvs2svn FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 6531ae349f5Scvs2svn /* RTA */ 6541ae349f5Scvs2svn { 6551ae349f5Scvs2svn switch (fp->state) { 6561ae349f5Scvs2svn case ST_CLOSING: 6576d666775SBrian Somers (*fp->fn->LayerFinish)(fp); 658455aabc3SBrian Somers NewState(fp, ST_CLOSED); 6596d666775SBrian Somers (*fp->parent->LayerFinish)(fp->parent->object, fp); 6601ae349f5Scvs2svn break; 6611ae349f5Scvs2svn case ST_STOPPING: 6626d666775SBrian Somers (*fp->fn->LayerFinish)(fp); 663455aabc3SBrian Somers NewState(fp, ST_STOPPED); 6646d666775SBrian Somers (*fp->parent->LayerFinish)(fp->parent->object, fp); 6651ae349f5Scvs2svn break; 6661ae349f5Scvs2svn case ST_ACKRCVD: 6671ae349f5Scvs2svn NewState(fp, ST_REQSENT); 6681ae349f5Scvs2svn break; 6691ae349f5Scvs2svn case ST_OPENED: 6706d666775SBrian Somers (*fp->fn->LayerDown)(fp); 6711ae349f5Scvs2svn FsmSendConfigReq(fp); 6721ae349f5Scvs2svn NewState(fp, ST_REQSENT); 6736d666775SBrian Somers (*fp->parent->LayerDown)(fp->parent->object, fp); 6741ae349f5Scvs2svn break; 6751ae349f5Scvs2svn } 6761ae349f5Scvs2svn pfree(bp); 6771ae349f5Scvs2svn } 6781ae349f5Scvs2svn 6791ae349f5Scvs2svn static void 6801ae349f5Scvs2svn FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 6811ae349f5Scvs2svn /* RCJ */ 6821ae349f5Scvs2svn { 68330c2f2ffSBrian Somers struct fsm_decode dec; 6841ae349f5Scvs2svn int plen, flen; 6851ae349f5Scvs2svn 6861ae349f5Scvs2svn plen = plength(bp); 6871ae349f5Scvs2svn flen = ntohs(lhp->length) - sizeof *lhp; 6881ae349f5Scvs2svn if (plen < flen) { 6891ae349f5Scvs2svn pfree(bp); 6901ae349f5Scvs2svn return; 6911ae349f5Scvs2svn } 6921ae349f5Scvs2svn 6931ae349f5Scvs2svn /* 6941ae349f5Scvs2svn * Check and process easy case 6951ae349f5Scvs2svn */ 6961ae349f5Scvs2svn switch (fp->state) { 6971ae349f5Scvs2svn case ST_INITIAL: 6981ae349f5Scvs2svn case ST_STARTING: 6991e991daaSBrian Somers LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", State2Nam(fp->state)); 7001ae349f5Scvs2svn pfree(bp); 7011ae349f5Scvs2svn return; 7021ae349f5Scvs2svn case ST_CLOSED: 7031ae349f5Scvs2svn case ST_STOPPED: 7042267893fSBrian Somers (*fp->fn->SendTerminateAck)(fp, lhp->id); 7051ae349f5Scvs2svn pfree(bp); 7061ae349f5Scvs2svn return; 7071ae349f5Scvs2svn case ST_CLOSING: 7081ae349f5Scvs2svn case ST_STOPPING: 7091ae349f5Scvs2svn pfree(bp); 7101ae349f5Scvs2svn return; 7111ae349f5Scvs2svn } 7121ae349f5Scvs2svn 71330c2f2ffSBrian Somers dec.ackend = dec.ack; 71430c2f2ffSBrian Somers dec.nakend = dec.nak; 71530c2f2ffSBrian Somers dec.rejend = dec.rej; 71630c2f2ffSBrian Somers (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec); 7172267893fSBrian Somers if (flen < sizeof(struct fsmconfig)) 7182267893fSBrian Somers LogPrintf(fp->LogLevel, " [EMPTY]\n"); 7191ae349f5Scvs2svn 7201ae349f5Scvs2svn switch (fp->state) { 7211ae349f5Scvs2svn case ST_REQSENT: 7221ae349f5Scvs2svn case ST_ACKSENT: 7231ae349f5Scvs2svn FsmInitRestartCounter(fp); 7241ae349f5Scvs2svn FsmSendConfigReq(fp); 7251ae349f5Scvs2svn break; 7261ae349f5Scvs2svn case ST_OPENED: 7276d666775SBrian Somers (*fp->fn->LayerDown)(fp); 728455aabc3SBrian Somers FsmSendConfigReq(fp); 729455aabc3SBrian Somers NewState(fp, ST_REQSENT); 7306d666775SBrian Somers (*fp->parent->LayerDown)(fp->parent->object, fp); 731455aabc3SBrian Somers break; 7321ae349f5Scvs2svn case ST_ACKRCVD: 7331ae349f5Scvs2svn FsmSendConfigReq(fp); 7341ae349f5Scvs2svn NewState(fp, ST_REQSENT); 7351ae349f5Scvs2svn break; 7361ae349f5Scvs2svn } 7371ae349f5Scvs2svn pfree(bp); 7381ae349f5Scvs2svn } 7391ae349f5Scvs2svn 7401ae349f5Scvs2svn static void 7411ae349f5Scvs2svn FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 7421ae349f5Scvs2svn { 7431ae349f5Scvs2svn pfree(bp); 7441ae349f5Scvs2svn } 7451ae349f5Scvs2svn 7461ae349f5Scvs2svn static void 7471ae349f5Scvs2svn FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 7481ae349f5Scvs2svn { 7498c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 7501ae349f5Scvs2svn u_short *sp, proto; 7511ae349f5Scvs2svn 7521ae349f5Scvs2svn sp = (u_short *) MBUF_CTOP(bp); 7531ae349f5Scvs2svn proto = ntohs(*sp); 75463258dccSBrian Somers LogPrintf(fp->LogLevel, "-- Protocol 0x%04x (%s) was rejected.\n", 75563258dccSBrian Somers proto, hdlc_Protocol2Nam(proto)); 7561ae349f5Scvs2svn 7571ae349f5Scvs2svn switch (proto) { 7581ae349f5Scvs2svn case PROTO_LQR: 7598c07a7b2SBrian Somers if (p) 7608c07a7b2SBrian Somers StopLqr(p, LQM_LQR); 7618c07a7b2SBrian Somers else 7628c07a7b2SBrian Somers LogPrintf(LogERROR, "FsmRecvProtoRej: Not a physical link !\n"); 7631ae349f5Scvs2svn break; 7641ae349f5Scvs2svn case PROTO_CCP: 765dc0fdb6bSBrian Somers if (fp->proto == PROTO_LCP) { 766dc0fdb6bSBrian Somers fp = &lcp2ccp(fsm2lcp(fp))->fsm; 7676d666775SBrian Somers (*fp->fn->LayerFinish)(fp); 7681ae349f5Scvs2svn switch (fp->state) { 7691ae349f5Scvs2svn case ST_CLOSED: 7701ae349f5Scvs2svn case ST_CLOSING: 7711ae349f5Scvs2svn NewState(fp, ST_CLOSED); 7721ae349f5Scvs2svn default: 7731ae349f5Scvs2svn NewState(fp, ST_STOPPED); 7741ae349f5Scvs2svn break; 7751ae349f5Scvs2svn } 7766d666775SBrian Somers (*fp->parent->LayerFinish)(fp->parent->object, fp); 777dc0fdb6bSBrian Somers } 7781ae349f5Scvs2svn break; 7791ae349f5Scvs2svn } 7801ae349f5Scvs2svn pfree(bp); 7811ae349f5Scvs2svn } 7821ae349f5Scvs2svn 7831ae349f5Scvs2svn static void 7841ae349f5Scvs2svn FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 7851ae349f5Scvs2svn { 786dc0fdb6bSBrian Somers struct lcp *lcp = fsm2lcp(fp); 7871ae349f5Scvs2svn u_char *cp; 7881ae349f5Scvs2svn u_long *lp, magic; 7891ae349f5Scvs2svn 790dc0fdb6bSBrian Somers if (lcp) { 7911ae349f5Scvs2svn cp = MBUF_CTOP(bp); 7921ae349f5Scvs2svn lp = (u_long *) cp; 7931ae349f5Scvs2svn magic = ntohl(*lp); 794dc0fdb6bSBrian Somers if (magic != lcp->his_magic) { 7951ae349f5Scvs2svn LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n"); 7961ae349f5Scvs2svn /* XXX: We should send terminate request */ 7971ae349f5Scvs2svn } 7981ae349f5Scvs2svn if (fp->state == ST_OPENED) { 799dc0fdb6bSBrian Somers *lp = htonl(lcp->want_magic); /* Insert local magic number */ 8001ae349f5Scvs2svn FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp)); 8011ae349f5Scvs2svn } 802dc0fdb6bSBrian Somers } 8031ae349f5Scvs2svn pfree(bp); 8041ae349f5Scvs2svn } 8051ae349f5Scvs2svn 8061ae349f5Scvs2svn static void 8071ae349f5Scvs2svn FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 8081ae349f5Scvs2svn { 809dc0fdb6bSBrian Somers struct lcp *lcp = fsm2lcp(fp); 8101ae349f5Scvs2svn u_long *lp, magic; 8111ae349f5Scvs2svn 812dc0fdb6bSBrian Somers if (lcp) { 8131ae349f5Scvs2svn lp = (u_long *) MBUF_CTOP(bp); 8141ae349f5Scvs2svn magic = ntohl(*lp); 815879ed6faSBrian Somers /* Tolerate echo replies with either magic number */ 816dc0fdb6bSBrian Somers if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) { 817dc0fdb6bSBrian Somers LogPrintf(LogWARN, 818dc0fdb6bSBrian Somers "RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n", 819dc0fdb6bSBrian Somers lcp->his_magic, magic); 8201ae349f5Scvs2svn /* 8211ae349f5Scvs2svn * XXX: We should send terminate request. But poor implementation may die 8221ae349f5Scvs2svn * as a result. 8231ae349f5Scvs2svn */ 8241ae349f5Scvs2svn } 825879ed6faSBrian Somers RecvEchoLqr(fp, bp); 826dc0fdb6bSBrian Somers } 8271ae349f5Scvs2svn pfree(bp); 8281ae349f5Scvs2svn } 8291ae349f5Scvs2svn 8301ae349f5Scvs2svn static void 8311ae349f5Scvs2svn FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 8321ae349f5Scvs2svn { 8331ae349f5Scvs2svn pfree(bp); 8341ae349f5Scvs2svn } 8351ae349f5Scvs2svn 8361ae349f5Scvs2svn static void 8371ae349f5Scvs2svn FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 8381ae349f5Scvs2svn { 8391ae349f5Scvs2svn pfree(bp); 8401ae349f5Scvs2svn } 8411ae349f5Scvs2svn 8421ae349f5Scvs2svn static void 8431ae349f5Scvs2svn FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 8441ae349f5Scvs2svn { 8451ae349f5Scvs2svn pfree(bp); 8461ae349f5Scvs2svn } 8471ae349f5Scvs2svn 8481ae349f5Scvs2svn static void 8491ae349f5Scvs2svn FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 8501ae349f5Scvs2svn { 851503a7782SBrian Somers (*fp->fn->RecvResetReq)(fp); 8521ae349f5Scvs2svn /* 8531ae349f5Scvs2svn * All sendable compressed packets are queued in the PRI_NORMAL modem 8541ae349f5Scvs2svn * output queue.... dump 'em to the priority queue so that they arrive 8551ae349f5Scvs2svn * at the peer before our ResetAck. 8561ae349f5Scvs2svn */ 8578c07a7b2SBrian Somers link_SequenceQueue(fp->link); 8581ae349f5Scvs2svn FsmOutput(fp, CODE_RESETACK, lhp->id, NULL, 0); 8591ae349f5Scvs2svn pfree(bp); 8601ae349f5Scvs2svn } 8611ae349f5Scvs2svn 8621ae349f5Scvs2svn static void 8631ae349f5Scvs2svn FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 8641ae349f5Scvs2svn { 865503a7782SBrian Somers (*fp->fn->RecvResetAck)(fp, lhp->id); 8661ae349f5Scvs2svn pfree(bp); 8671ae349f5Scvs2svn } 8681ae349f5Scvs2svn 8691ae349f5Scvs2svn void 8701ae349f5Scvs2svn FsmInput(struct fsm *fp, struct mbuf *bp) 8711ae349f5Scvs2svn { 8721ae349f5Scvs2svn int len; 8731ae349f5Scvs2svn struct fsmheader *lhp; 8741ae349f5Scvs2svn const struct fsmcodedesc *codep; 8751ae349f5Scvs2svn 8761ae349f5Scvs2svn len = plength(bp); 8771ae349f5Scvs2svn if (len < sizeof(struct fsmheader)) { 8781ae349f5Scvs2svn pfree(bp); 8791ae349f5Scvs2svn return; 8801ae349f5Scvs2svn } 8811ae349f5Scvs2svn lhp = (struct fsmheader *) MBUF_CTOP(bp); 8827308ec68SBrian Somers if (lhp->code == 0 || lhp->code > fp->max_code || 8837308ec68SBrian Somers lhp->code > sizeof FsmCodes / sizeof *FsmCodes) { 8841ae349f5Scvs2svn pfree(bp); /* XXX: Should send code reject */ 8851ae349f5Scvs2svn return; 8861ae349f5Scvs2svn } 8871ae349f5Scvs2svn bp->offset += sizeof(struct fsmheader); 8881ae349f5Scvs2svn bp->cnt -= sizeof(struct fsmheader); 8891ae349f5Scvs2svn 8901ae349f5Scvs2svn codep = FsmCodes + lhp->code - 1; 8912267893fSBrian Somers if (lhp->id != fp->reqid && codep->check_reqid && Enabled(ConfIdCheck)) { 8922267893fSBrian Somers LogPrintf(fp->LogLevel, "Recv%s(%d), dropped (expected %d)\n", 8932267893fSBrian Somers codep->name, lhp->id, fp->reqid); 8942267893fSBrian Somers return; 8952267893fSBrian Somers } 8962267893fSBrian Somers 8972267893fSBrian Somers LogPrintf(fp->LogLevel, "Recv%s(%d) state = %s\n", 8981e991daaSBrian Somers codep->name, lhp->id, State2Nam(fp->state)); 8992267893fSBrian Somers 9001ae349f5Scvs2svn if (LogIsKept(LogDEBUG)) 9011ae349f5Scvs2svn LogMemory(); 9022267893fSBrian Somers 9032267893fSBrian Somers if (codep->inc_reqid && (lhp->id == fp->reqid || 9042267893fSBrian Somers (!Enabled(ConfIdCheck) && codep->check_reqid))) 9052267893fSBrian Somers fp->reqid++; /* That's the end of that ``exchange''.... */ 9062267893fSBrian Somers 9072267893fSBrian Somers (codep->recv)(fp, lhp, bp); 9082267893fSBrian Somers 9091ae349f5Scvs2svn if (LogIsKept(LogDEBUG)) 9101ae349f5Scvs2svn LogMemory(); 9111ae349f5Scvs2svn } 912503a7782SBrian Somers 913503a7782SBrian Somers void 914503a7782SBrian Somers NullRecvResetReq(struct fsm *fp) 915503a7782SBrian Somers { 916503a7782SBrian Somers LogPrintf(fp->LogLevel, "Oops - received unexpected reset req\n"); 917503a7782SBrian Somers } 918503a7782SBrian Somers 919503a7782SBrian Somers void 920503a7782SBrian Somers NullRecvResetAck(struct fsm *fp, u_char id) 921503a7782SBrian Somers { 922503a7782SBrian Somers LogPrintf(fp->LogLevel, "Oops - received unexpected reset ack\n"); 923503a7782SBrian Somers } 924