1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * PPP Finite State Machine for LCP/IPCP 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 2098baf7c8SBrian Somers * $Id: fsm.c,v 1.25 1997/12/24 09:28:58 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai * o Refer loglevel for log output 24af57ed9fSAtsushi Murai * o Better option log display 25af57ed9fSAtsushi Murai */ 2675240ed1SBrian Somers #include <sys/param.h> 2775240ed1SBrian Somers #include <netinet/in.h> 2875240ed1SBrian Somers 2975240ed1SBrian Somers #include <stdio.h> 3075240ed1SBrian Somers #include <string.h> 3175240ed1SBrian Somers #include <termios.h> 3275240ed1SBrian Somers 33b6e82f33SBrian Somers #include "command.h" 3475240ed1SBrian Somers #include "mbuf.h" 3575240ed1SBrian Somers #include "log.h" 3675240ed1SBrian Somers #include "defs.h" 3775240ed1SBrian Somers #include "timer.h" 38af57ed9fSAtsushi Murai #include "fsm.h" 39af57ed9fSAtsushi Murai #include "hdlc.h" 40af57ed9fSAtsushi Murai #include "lqr.h" 41af57ed9fSAtsushi Murai #include "lcpproto.h" 42af57ed9fSAtsushi Murai #include "lcp.h" 43ed6a16c1SPoul-Henning Kamp #include "ccp.h" 4471144dc5SBrian Somers #include "modem.h" 4571144dc5SBrian Somers #include "loadalias.h" 4671144dc5SBrian Somers #include "vars.h" 47af57ed9fSAtsushi Murai 4875240ed1SBrian Somers u_char AckBuff[200]; 4975240ed1SBrian Somers u_char NakBuff[200]; 5075240ed1SBrian Somers u_char RejBuff[100]; 5175240ed1SBrian Somers u_char ReqBuff[200]; 5275240ed1SBrian Somers u_char *ackp = NULL; 5375240ed1SBrian Somers u_char *nakp = NULL; 5475240ed1SBrian Somers u_char *rejp = NULL; 5575240ed1SBrian Somers 5675240ed1SBrian Somers static void FsmSendConfigReq(struct fsm *); 5775240ed1SBrian Somers static void FsmSendTerminateReq(struct fsm *); 5875240ed1SBrian Somers static void FsmInitRestartCounter(struct fsm *); 59af57ed9fSAtsushi Murai 60ed6a16c1SPoul-Henning Kamp char const *StateNames[] = { 61af57ed9fSAtsushi Murai "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 62927145beSBrian Somers "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened", 63af57ed9fSAtsushi Murai }; 64af57ed9fSAtsushi Murai 6571144dc5SBrian Somers static void 66b6e82f33SBrian Somers StoppedTimeout(void *v) 6771144dc5SBrian Somers { 68b6e82f33SBrian Somers struct fsm *fp = (struct fsm *)v; 69b6e82f33SBrian Somers 70cb611434SBrian Somers LogPrintf(fp->LogLevel, "Stopped timer expired\n"); 7171144dc5SBrian Somers if (modem != -1) 7271144dc5SBrian Somers DownConnection(); 7371144dc5SBrian Somers else 7471144dc5SBrian Somers FsmDown(fp); 7571144dc5SBrian Somers } 7671144dc5SBrian Somers 77af57ed9fSAtsushi Murai void 78944f7098SBrian Somers FsmInit(struct fsm * fp) 79af57ed9fSAtsushi Murai { 80927145beSBrian Somers LogPrintf(LogDEBUG, "FsmInit\n"); 81af57ed9fSAtsushi Murai fp->state = ST_INITIAL; 82af57ed9fSAtsushi Murai fp->reqid = 1; 83af57ed9fSAtsushi Murai fp->restart = 1; 84af57ed9fSAtsushi Murai fp->maxconfig = 3; 85af57ed9fSAtsushi Murai } 86af57ed9fSAtsushi Murai 8775240ed1SBrian Somers static void 88944f7098SBrian Somers NewState(struct fsm * fp, int new) 89af57ed9fSAtsushi Murai { 90cb611434SBrian Somers LogPrintf(fp->LogLevel, "State change %s --> %s\n", 91927145beSBrian Somers StateNames[fp->state], StateNames[new]); 92cb611434SBrian Somers if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING) 93cb611434SBrian Somers StopTimer(&fp->StoppedTimer); 94af57ed9fSAtsushi Murai fp->state = new; 9571144dc5SBrian Somers if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) { 96af57ed9fSAtsushi Murai StopTimer(&fp->FsmTimer); 97cb611434SBrian Somers if (new == ST_STOPPED && fp->StoppedTimer.load) { 98cb611434SBrian Somers fp->StoppedTimer.state = TIMER_STOPPED; 99cb611434SBrian Somers fp->StoppedTimer.func = StoppedTimeout; 100cb611434SBrian Somers fp->StoppedTimer.arg = (void *) fp; 101cb611434SBrian Somers StartTimer(&fp->StoppedTimer); 10271144dc5SBrian Somers } 10371144dc5SBrian Somers } 104af57ed9fSAtsushi Murai } 105af57ed9fSAtsushi Murai 106af57ed9fSAtsushi Murai void 107944f7098SBrian Somers FsmOutput(struct fsm * fp, u_int code, u_int id, u_char * ptr, int count) 108af57ed9fSAtsushi Murai { 109af57ed9fSAtsushi Murai int plen; 110af57ed9fSAtsushi Murai struct fsmheader lh; 111af57ed9fSAtsushi Murai struct mbuf *bp; 112af57ed9fSAtsushi Murai 113af57ed9fSAtsushi Murai plen = sizeof(struct fsmheader) + count; 114af57ed9fSAtsushi Murai lh.code = code; 115af57ed9fSAtsushi Murai lh.id = id; 116af57ed9fSAtsushi Murai lh.length = htons(plen); 117af57ed9fSAtsushi Murai bp = mballoc(plen, MB_FSM); 11875240ed1SBrian Somers memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 119af57ed9fSAtsushi Murai if (count) 12075240ed1SBrian Somers memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count); 121927145beSBrian Somers LogDumpBp(LogDEBUG, "FsmOutput", bp); 12276bd0c0aSDoug Rabson HdlcOutput(PRI_LINK, fp->proto, bp); 123af57ed9fSAtsushi Murai } 124af57ed9fSAtsushi Murai 125af57ed9fSAtsushi Murai void 126944f7098SBrian Somers FsmOpen(struct fsm * fp) 127af57ed9fSAtsushi Murai { 128af57ed9fSAtsushi Murai switch (fp->state) { 129af57ed9fSAtsushi Murai case ST_INITIAL: 130af57ed9fSAtsushi Murai (fp->LayerStart) (fp); 131af57ed9fSAtsushi Murai NewState(fp, ST_STARTING); 132af57ed9fSAtsushi Murai break; 133af57ed9fSAtsushi Murai case ST_STARTING: 134af57ed9fSAtsushi Murai break; 135af57ed9fSAtsushi Murai case ST_CLOSED: 136af57ed9fSAtsushi Murai if (fp->open_mode == OPEN_PASSIVE) { 137af57ed9fSAtsushi Murai NewState(fp, ST_STOPPED); 138af57ed9fSAtsushi Murai } else { 139af57ed9fSAtsushi Murai FsmInitRestartCounter(fp); 140af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 141af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 142af57ed9fSAtsushi Murai } 143af57ed9fSAtsushi Murai break; 144af57ed9fSAtsushi Murai case ST_STOPPED: /* XXX: restart option */ 145af57ed9fSAtsushi Murai case ST_REQSENT: 146af57ed9fSAtsushi Murai case ST_ACKRCVD: 147af57ed9fSAtsushi Murai case ST_ACKSENT: 148af57ed9fSAtsushi Murai case ST_OPENED: /* XXX: restart option */ 149af57ed9fSAtsushi Murai break; 150af57ed9fSAtsushi Murai case ST_CLOSING: /* XXX: restart option */ 151af57ed9fSAtsushi Murai case ST_STOPPING: /* XXX: restart option */ 152af57ed9fSAtsushi Murai NewState(fp, ST_STOPPING); 153af57ed9fSAtsushi Murai break; 154af57ed9fSAtsushi Murai } 155af57ed9fSAtsushi Murai } 156af57ed9fSAtsushi Murai 157af57ed9fSAtsushi Murai void 158944f7098SBrian Somers FsmUp(struct fsm * fp) 159af57ed9fSAtsushi Murai { 160af57ed9fSAtsushi Murai switch (fp->state) { 161af57ed9fSAtsushi Murai case ST_INITIAL: 162af57ed9fSAtsushi Murai NewState(fp, ST_CLOSED); 163af57ed9fSAtsushi Murai break; 164af57ed9fSAtsushi Murai case ST_STARTING: 165af57ed9fSAtsushi Murai FsmInitRestartCounter(fp); 166af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 167af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 168af57ed9fSAtsushi Murai break; 169af57ed9fSAtsushi Murai default: 170cb611434SBrian Somers LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]); 171af57ed9fSAtsushi Murai break; 172af57ed9fSAtsushi Murai } 173af57ed9fSAtsushi Murai } 174af57ed9fSAtsushi Murai 175af57ed9fSAtsushi Murai void 176944f7098SBrian Somers FsmDown(struct fsm * fp) 177af57ed9fSAtsushi Murai { 178af57ed9fSAtsushi Murai switch (fp->state) { 179af57ed9fSAtsushi Murai case ST_CLOSED: 180af57ed9fSAtsushi Murai case ST_CLOSING: 181af57ed9fSAtsushi Murai NewState(fp, ST_INITIAL); 182af57ed9fSAtsushi Murai break; 183af57ed9fSAtsushi Murai case ST_STOPPED: 184af57ed9fSAtsushi Murai (fp->LayerStart) (fp); 185af57ed9fSAtsushi Murai /* Fall into.. */ 186af57ed9fSAtsushi Murai case ST_STOPPING: 187af57ed9fSAtsushi Murai case ST_REQSENT: 188af57ed9fSAtsushi Murai case ST_ACKRCVD: 189af57ed9fSAtsushi Murai case ST_ACKSENT: 190af57ed9fSAtsushi Murai NewState(fp, ST_STARTING); 191af57ed9fSAtsushi Murai break; 192af57ed9fSAtsushi Murai case ST_OPENED: 193af57ed9fSAtsushi Murai (fp->LayerDown) (fp); 194af57ed9fSAtsushi Murai NewState(fp, ST_STARTING); 195af57ed9fSAtsushi Murai break; 196af57ed9fSAtsushi Murai } 197af57ed9fSAtsushi Murai } 198af57ed9fSAtsushi Murai 199af57ed9fSAtsushi Murai void 200944f7098SBrian Somers FsmClose(struct fsm * fp) 201af57ed9fSAtsushi Murai { 202af57ed9fSAtsushi Murai switch (fp->state) { 203af57ed9fSAtsushi Murai case ST_STARTING: 204af57ed9fSAtsushi Murai NewState(fp, ST_INITIAL); 205af57ed9fSAtsushi Murai break; 206af57ed9fSAtsushi Murai case ST_STOPPED: 207af57ed9fSAtsushi Murai NewState(fp, ST_CLOSED); 208af57ed9fSAtsushi Murai break; 209af57ed9fSAtsushi Murai case ST_STOPPING: 210af57ed9fSAtsushi Murai NewState(fp, ST_CLOSING); 211af57ed9fSAtsushi Murai break; 212af57ed9fSAtsushi Murai case ST_OPENED: 213af57ed9fSAtsushi Murai (fp->LayerDown) (fp); 214af57ed9fSAtsushi Murai /* Fall down */ 215af57ed9fSAtsushi Murai case ST_REQSENT: 216af57ed9fSAtsushi Murai case ST_ACKRCVD: 217af57ed9fSAtsushi Murai case ST_ACKSENT: 218af57ed9fSAtsushi Murai FsmInitRestartCounter(fp); 219af57ed9fSAtsushi Murai FsmSendTerminateReq(fp); 220af57ed9fSAtsushi Murai NewState(fp, ST_CLOSING); 221af57ed9fSAtsushi Murai break; 222af57ed9fSAtsushi Murai } 223af57ed9fSAtsushi Murai } 224af57ed9fSAtsushi Murai 225af57ed9fSAtsushi Murai /* 226af57ed9fSAtsushi Murai * Send functions 227af57ed9fSAtsushi Murai */ 22875240ed1SBrian Somers static void 229944f7098SBrian Somers FsmSendConfigReq(struct fsm * fp) 230af57ed9fSAtsushi Murai { 231af57ed9fSAtsushi Murai if (--fp->maxconfig > 0) { 232af57ed9fSAtsushi Murai (fp->SendConfigReq) (fp); 233af57ed9fSAtsushi Murai StartTimer(&fp->FsmTimer); /* Start restart timer */ 234af57ed9fSAtsushi Murai fp->restart--; /* Decrement restart counter */ 235af57ed9fSAtsushi Murai } else { 236af57ed9fSAtsushi Murai FsmClose(fp); 237af57ed9fSAtsushi Murai } 238af57ed9fSAtsushi Murai } 239af57ed9fSAtsushi Murai 24075240ed1SBrian Somers static void 241944f7098SBrian Somers FsmSendTerminateReq(struct fsm * fp) 242af57ed9fSAtsushi Murai { 243cb611434SBrian Somers LogPrintf(fp->LogLevel, "SendTerminateReq.\n"); 244af57ed9fSAtsushi Murai FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0); 245af57ed9fSAtsushi Murai (fp->SendTerminateReq) (fp); 246af57ed9fSAtsushi Murai StartTimer(&fp->FsmTimer); /* Start restart timer */ 247af57ed9fSAtsushi Murai fp->restart--; /* Decrement restart counter */ 248af57ed9fSAtsushi Murai } 249af57ed9fSAtsushi Murai 250af57ed9fSAtsushi Murai static void 251944f7098SBrian Somers FsmSendConfigAck(struct fsm * fp, 252944f7098SBrian Somers struct fsmheader * lhp, 253944f7098SBrian Somers u_char * option, 254944f7098SBrian Somers int count) 255af57ed9fSAtsushi Murai { 256cb611434SBrian Somers LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]); 25753c9f6c0SAtsushi Murai (fp->DecodeConfig) (option, count, MODE_NOP); 258af57ed9fSAtsushi Murai FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count); 259af57ed9fSAtsushi Murai } 260af57ed9fSAtsushi Murai 261af57ed9fSAtsushi Murai static void 262944f7098SBrian Somers FsmSendConfigRej(struct fsm * fp, 263944f7098SBrian Somers struct fsmheader * lhp, 264944f7098SBrian Somers u_char * option, 265944f7098SBrian Somers int count) 266af57ed9fSAtsushi Murai { 267cb611434SBrian Somers LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]); 26853c9f6c0SAtsushi Murai (fp->DecodeConfig) (option, count, MODE_NOP); 269af57ed9fSAtsushi Murai FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count); 270af57ed9fSAtsushi Murai } 271af57ed9fSAtsushi Murai 272af57ed9fSAtsushi Murai static void 273944f7098SBrian Somers FsmSendConfigNak(struct fsm * fp, 274944f7098SBrian Somers struct fsmheader * lhp, 275944f7098SBrian Somers u_char * option, 276944f7098SBrian Somers int count) 277af57ed9fSAtsushi Murai { 278cb611434SBrian Somers LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]); 27953c9f6c0SAtsushi Murai (fp->DecodeConfig) (option, count, MODE_NOP); 280af57ed9fSAtsushi Murai FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count); 281af57ed9fSAtsushi Murai } 282af57ed9fSAtsushi Murai 283af57ed9fSAtsushi Murai /* 284af57ed9fSAtsushi Murai * Timeout actions 285af57ed9fSAtsushi Murai */ 28675240ed1SBrian Somers static void 287b6e82f33SBrian Somers FsmTimeout(void *v) 288af57ed9fSAtsushi Murai { 289b6e82f33SBrian Somers struct fsm *fp = (struct fsm *)v; 290b6e82f33SBrian Somers 291af57ed9fSAtsushi Murai if (fp->restart) { 292af57ed9fSAtsushi Murai switch (fp->state) { 293af57ed9fSAtsushi Murai case ST_CLOSING: 294af57ed9fSAtsushi Murai case ST_STOPPING: 295af57ed9fSAtsushi Murai FsmSendTerminateReq(fp); 296af57ed9fSAtsushi Murai break; 297af57ed9fSAtsushi Murai case ST_REQSENT: 298af57ed9fSAtsushi Murai case ST_ACKSENT: 299af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 300af57ed9fSAtsushi Murai break; 301af57ed9fSAtsushi Murai case ST_ACKRCVD: 302af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 303af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 304af57ed9fSAtsushi Murai break; 305af57ed9fSAtsushi Murai } 306af57ed9fSAtsushi Murai StartTimer(&fp->FsmTimer); 307af57ed9fSAtsushi Murai } else { 308af57ed9fSAtsushi Murai switch (fp->state) { 309af57ed9fSAtsushi Murai case ST_CLOSING: 310af57ed9fSAtsushi Murai NewState(fp, ST_CLOSED); 311af57ed9fSAtsushi Murai (fp->LayerFinish) (fp); 312af57ed9fSAtsushi Murai break; 313af57ed9fSAtsushi Murai case ST_STOPPING: 314af57ed9fSAtsushi Murai NewState(fp, ST_STOPPED); 315af57ed9fSAtsushi Murai (fp->LayerFinish) (fp); 316af57ed9fSAtsushi Murai break; 317af57ed9fSAtsushi Murai case ST_REQSENT: /* XXX: 3p */ 318af57ed9fSAtsushi Murai case ST_ACKSENT: 319af57ed9fSAtsushi Murai case ST_ACKRCVD: 320af57ed9fSAtsushi Murai NewState(fp, ST_STOPPED); 321af57ed9fSAtsushi Murai (fp->LayerFinish) (fp); 322af57ed9fSAtsushi Murai break; 323af57ed9fSAtsushi Murai } 324af57ed9fSAtsushi Murai } 325af57ed9fSAtsushi Murai } 326af57ed9fSAtsushi Murai 32775240ed1SBrian Somers static void 328944f7098SBrian Somers FsmInitRestartCounter(struct fsm * fp) 329af57ed9fSAtsushi Murai { 330af57ed9fSAtsushi Murai StopTimer(&fp->FsmTimer); 331af57ed9fSAtsushi Murai fp->FsmTimer.state = TIMER_STOPPED; 332af57ed9fSAtsushi Murai fp->FsmTimer.func = FsmTimeout; 333af57ed9fSAtsushi Murai fp->FsmTimer.arg = (void *) fp; 334af57ed9fSAtsushi Murai (fp->InitRestartCounter) (fp); 335af57ed9fSAtsushi Murai } 336af57ed9fSAtsushi Murai 337af57ed9fSAtsushi Murai /* 338af57ed9fSAtsushi Murai * Actions when receive packets 339af57ed9fSAtsushi Murai */ 34075240ed1SBrian Somers static void 341944f7098SBrian Somers FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 342944f7098SBrian Somers /* RCR */ 343af57ed9fSAtsushi Murai { 34453c9f6c0SAtsushi Murai int plen, flen; 345af57ed9fSAtsushi Murai int ackaction = 0; 346af57ed9fSAtsushi Murai 347af57ed9fSAtsushi Murai plen = plength(bp); 34870ee81ffSBrian Somers flen = ntohs(lhp->length) - sizeof *lhp; 34953c9f6c0SAtsushi Murai if (plen < flen) { 350afc7fa2cSBrian Somers LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)\n", 351afc7fa2cSBrian Somers plen, flen); 352af57ed9fSAtsushi Murai pfree(bp); 353af57ed9fSAtsushi Murai return; 354af57ed9fSAtsushi Murai } 355af57ed9fSAtsushi Murai 356af57ed9fSAtsushi Murai /* 357af57ed9fSAtsushi Murai * Check and process easy case 358af57ed9fSAtsushi Murai */ 359af57ed9fSAtsushi Murai switch (fp->state) { 360af57ed9fSAtsushi Murai case ST_INITIAL: 361af57ed9fSAtsushi Murai case ST_STARTING: 362cb611434SBrian Somers LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]); 363af57ed9fSAtsushi Murai pfree(bp); 364af57ed9fSAtsushi Murai return; 365af57ed9fSAtsushi Murai case ST_CLOSED: 366af57ed9fSAtsushi Murai (fp->SendTerminateAck) (fp); 367af57ed9fSAtsushi Murai pfree(bp); 368af57ed9fSAtsushi Murai return; 369af57ed9fSAtsushi Murai case ST_CLOSING: 370bcc332bdSBrian Somers LogPrintf(fp->LogLevel, "Error: Got ConfigReq while state = %d\n", 371bcc332bdSBrian Somers fp->state); 372a9c503afSBrian Somers case ST_STOPPING: 373af57ed9fSAtsushi Murai pfree(bp); 374af57ed9fSAtsushi Murai return; 375af57ed9fSAtsushi Murai } 376af57ed9fSAtsushi Murai 37753c9f6c0SAtsushi Murai (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REQ); 378af57ed9fSAtsushi Murai 379af57ed9fSAtsushi Murai if (nakp == NakBuff && rejp == RejBuff) 380af57ed9fSAtsushi Murai ackaction = 1; 381af57ed9fSAtsushi Murai 382af57ed9fSAtsushi Murai switch (fp->state) { 383af57ed9fSAtsushi Murai case ST_OPENED: 384af57ed9fSAtsushi Murai (fp->LayerDown) (fp); 385af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 386af57ed9fSAtsushi Murai break; 387af57ed9fSAtsushi Murai case ST_STOPPED: 388af57ed9fSAtsushi Murai FsmInitRestartCounter(fp); 389af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 390af57ed9fSAtsushi Murai break; 391af57ed9fSAtsushi Murai } 392af57ed9fSAtsushi Murai 393af57ed9fSAtsushi Murai if (rejp != RejBuff) 394af57ed9fSAtsushi Murai FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff); 395af57ed9fSAtsushi Murai if (nakp != NakBuff) 396af57ed9fSAtsushi Murai FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff); 397af57ed9fSAtsushi Murai if (ackaction) 398af57ed9fSAtsushi Murai FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff); 399af57ed9fSAtsushi Murai 400af57ed9fSAtsushi Murai switch (fp->state) { 401af57ed9fSAtsushi Murai case ST_STOPPED: 402af57ed9fSAtsushi Murai case ST_OPENED: 403af57ed9fSAtsushi Murai if (ackaction) 404af57ed9fSAtsushi Murai NewState(fp, ST_ACKSENT); 405af57ed9fSAtsushi Murai else 406af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 407af57ed9fSAtsushi Murai break; 408af57ed9fSAtsushi Murai case ST_REQSENT: 409af57ed9fSAtsushi Murai if (ackaction) 410af57ed9fSAtsushi Murai NewState(fp, ST_ACKSENT); 411af57ed9fSAtsushi Murai break; 412af57ed9fSAtsushi Murai case ST_ACKRCVD: 413af57ed9fSAtsushi Murai if (ackaction) { 414af57ed9fSAtsushi Murai NewState(fp, ST_OPENED); 415af57ed9fSAtsushi Murai (fp->LayerUp) (fp); 416af57ed9fSAtsushi Murai } 417af57ed9fSAtsushi Murai break; 418af57ed9fSAtsushi Murai case ST_ACKSENT: 419af57ed9fSAtsushi Murai if (!ackaction) 420af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 421af57ed9fSAtsushi Murai break; 422af57ed9fSAtsushi Murai } 423af57ed9fSAtsushi Murai pfree(bp); 424af57ed9fSAtsushi Murai } 425af57ed9fSAtsushi Murai 42675240ed1SBrian Somers static void 427944f7098SBrian Somers FsmRecvConfigAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 428944f7098SBrian Somers /* RCA */ 429af57ed9fSAtsushi Murai { 430af57ed9fSAtsushi Murai switch (fp->state) { 431af57ed9fSAtsushi Murai case ST_CLOSED: 432af57ed9fSAtsushi Murai case ST_STOPPED: 433af57ed9fSAtsushi Murai (fp->SendTerminateAck) (fp); 434af57ed9fSAtsushi Murai break; 435af57ed9fSAtsushi Murai case ST_CLOSING: 436af57ed9fSAtsushi Murai case ST_STOPPING: 437af57ed9fSAtsushi Murai break; 438af57ed9fSAtsushi Murai case ST_REQSENT: 439af57ed9fSAtsushi Murai FsmInitRestartCounter(fp); 440af57ed9fSAtsushi Murai NewState(fp, ST_ACKRCVD); 441af57ed9fSAtsushi Murai break; 442af57ed9fSAtsushi Murai case ST_ACKRCVD: 443af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 444af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 445af57ed9fSAtsushi Murai break; 446af57ed9fSAtsushi Murai case ST_ACKSENT: 447af57ed9fSAtsushi Murai FsmInitRestartCounter(fp); 448af57ed9fSAtsushi Murai NewState(fp, ST_OPENED); 449af57ed9fSAtsushi Murai (fp->LayerUp) (fp); 450af57ed9fSAtsushi Murai break; 451af57ed9fSAtsushi Murai case ST_OPENED: 452af57ed9fSAtsushi Murai (fp->LayerDown) (fp); 453af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 454af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 455af57ed9fSAtsushi Murai break; 456af57ed9fSAtsushi Murai } 457af57ed9fSAtsushi Murai pfree(bp); 458af57ed9fSAtsushi Murai } 459af57ed9fSAtsushi Murai 46075240ed1SBrian Somers static void 461944f7098SBrian Somers FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 462944f7098SBrian Somers /* RCN */ 463af57ed9fSAtsushi Murai { 46453c9f6c0SAtsushi Murai int plen, flen; 465af57ed9fSAtsushi Murai 466af57ed9fSAtsushi Murai plen = plength(bp); 46770ee81ffSBrian Somers flen = ntohs(lhp->length) - sizeof *lhp; 46853c9f6c0SAtsushi Murai if (plen < flen) { 469af57ed9fSAtsushi Murai pfree(bp); 470af57ed9fSAtsushi Murai return; 471af57ed9fSAtsushi Murai } 472af57ed9fSAtsushi Murai 473af57ed9fSAtsushi Murai /* 474af57ed9fSAtsushi Murai * Check and process easy case 475af57ed9fSAtsushi Murai */ 476af57ed9fSAtsushi Murai switch (fp->state) { 477af57ed9fSAtsushi Murai case ST_INITIAL: 478af57ed9fSAtsushi Murai case ST_STARTING: 479cb611434SBrian Somers LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", StateNames[fp->state]); 480af57ed9fSAtsushi Murai pfree(bp); 481af57ed9fSAtsushi Murai return; 482af57ed9fSAtsushi Murai case ST_CLOSED: 483af57ed9fSAtsushi Murai case ST_STOPPED: 484af57ed9fSAtsushi Murai (fp->SendTerminateAck) (fp); 485af57ed9fSAtsushi Murai pfree(bp); 486af57ed9fSAtsushi Murai return; 487af57ed9fSAtsushi Murai case ST_CLOSING: 488af57ed9fSAtsushi Murai case ST_STOPPING: 489af57ed9fSAtsushi Murai pfree(bp); 490af57ed9fSAtsushi Murai return; 491af57ed9fSAtsushi Murai } 492af57ed9fSAtsushi Murai 49353c9f6c0SAtsushi Murai (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_NAK); 494af57ed9fSAtsushi Murai 495af57ed9fSAtsushi Murai switch (fp->state) { 496af57ed9fSAtsushi Murai case ST_REQSENT: 497af57ed9fSAtsushi Murai case ST_ACKSENT: 498af57ed9fSAtsushi Murai FsmInitRestartCounter(fp); 499af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 500af57ed9fSAtsushi Murai break; 501af57ed9fSAtsushi Murai case ST_OPENED: 502af57ed9fSAtsushi Murai (fp->LayerDown) (fp); 503af57ed9fSAtsushi Murai /* Fall down */ 504af57ed9fSAtsushi Murai case ST_ACKRCVD: 505af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 506af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 507af57ed9fSAtsushi Murai break; 508af57ed9fSAtsushi Murai } 509af57ed9fSAtsushi Murai 510af57ed9fSAtsushi Murai pfree(bp); 511af57ed9fSAtsushi Murai } 512af57ed9fSAtsushi Murai 51375240ed1SBrian Somers static void 514944f7098SBrian Somers FsmRecvTermReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 515944f7098SBrian Somers /* RTR */ 516af57ed9fSAtsushi Murai { 517af57ed9fSAtsushi Murai switch (fp->state) { 518af57ed9fSAtsushi Murai case ST_INITIAL: 519af57ed9fSAtsushi Murai case ST_STARTING: 520cb611434SBrian Somers LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", StateNames[fp->state]); 521af57ed9fSAtsushi Murai break; 522af57ed9fSAtsushi Murai case ST_CLOSED: 523af57ed9fSAtsushi Murai case ST_STOPPED: 524af57ed9fSAtsushi Murai case ST_CLOSING: 525af57ed9fSAtsushi Murai case ST_STOPPING: 526af57ed9fSAtsushi Murai case ST_REQSENT: 527af57ed9fSAtsushi Murai (fp->SendTerminateAck) (fp); 528af57ed9fSAtsushi Murai break; 529af57ed9fSAtsushi Murai case ST_ACKRCVD: 530af57ed9fSAtsushi Murai case ST_ACKSENT: 531af57ed9fSAtsushi Murai (fp->SendTerminateAck) (fp); 532af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 533af57ed9fSAtsushi Murai break; 534af57ed9fSAtsushi Murai case ST_OPENED: 5358f2fa0eeSBrian Somers (fp->LayerDown) (fp); 536af57ed9fSAtsushi Murai (fp->SendTerminateAck) (fp); 5378f2fa0eeSBrian Somers StartTimer(&fp->FsmTimer); /* Start restart timer */ 5388f2fa0eeSBrian Somers fp->restart = 0; 5398f2fa0eeSBrian Somers NewState(fp, ST_STOPPING); 540af57ed9fSAtsushi Murai break; 541af57ed9fSAtsushi Murai } 542af57ed9fSAtsushi Murai pfree(bp); 543af57ed9fSAtsushi Murai } 544af57ed9fSAtsushi Murai 54575240ed1SBrian Somers static void 546944f7098SBrian Somers FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 547944f7098SBrian Somers /* RTA */ 548af57ed9fSAtsushi Murai { 549af57ed9fSAtsushi Murai switch (fp->state) { 550af57ed9fSAtsushi Murai case ST_CLOSING: 551af57ed9fSAtsushi Murai NewState(fp, ST_CLOSED); 552af57ed9fSAtsushi Murai (fp->LayerFinish) (fp); 553af57ed9fSAtsushi Murai break; 554af57ed9fSAtsushi Murai case ST_STOPPING: 555af57ed9fSAtsushi Murai NewState(fp, ST_STOPPED); 556af57ed9fSAtsushi Murai (fp->LayerFinish) (fp); 557af57ed9fSAtsushi Murai break; 558af57ed9fSAtsushi Murai case ST_ACKRCVD: 559af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 560af57ed9fSAtsushi Murai break; 561af57ed9fSAtsushi Murai case ST_OPENED: 562af57ed9fSAtsushi Murai (fp->LayerDown) (fp); 563af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 564af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 565af57ed9fSAtsushi Murai break; 566af57ed9fSAtsushi Murai } 567af57ed9fSAtsushi Murai pfree(bp); 568af57ed9fSAtsushi Murai } 569af57ed9fSAtsushi Murai 57075240ed1SBrian Somers static void 571944f7098SBrian Somers FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 572944f7098SBrian Somers /* RCJ */ 573af57ed9fSAtsushi Murai { 57453c9f6c0SAtsushi Murai int plen, flen; 575af57ed9fSAtsushi Murai 576af57ed9fSAtsushi Murai plen = plength(bp); 57770ee81ffSBrian Somers flen = ntohs(lhp->length) - sizeof *lhp; 57853c9f6c0SAtsushi Murai if (plen < flen) { 579af57ed9fSAtsushi Murai pfree(bp); 580af57ed9fSAtsushi Murai return; 581af57ed9fSAtsushi Murai } 582cb611434SBrian Somers LogPrintf(fp->LogLevel, "RecvConfigRej.\n"); 583af57ed9fSAtsushi Murai 584af57ed9fSAtsushi Murai /* 585af57ed9fSAtsushi Murai * Check and process easy case 586af57ed9fSAtsushi Murai */ 587af57ed9fSAtsushi Murai switch (fp->state) { 588af57ed9fSAtsushi Murai case ST_INITIAL: 589af57ed9fSAtsushi Murai case ST_STARTING: 590cb611434SBrian Somers LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", StateNames[fp->state]); 591af57ed9fSAtsushi Murai pfree(bp); 592af57ed9fSAtsushi Murai return; 593af57ed9fSAtsushi Murai case ST_CLOSED: 594af57ed9fSAtsushi Murai case ST_STOPPED: 595af57ed9fSAtsushi Murai (fp->SendTerminateAck) (fp); 596af57ed9fSAtsushi Murai pfree(bp); 597af57ed9fSAtsushi Murai return; 598af57ed9fSAtsushi Murai case ST_CLOSING: 599af57ed9fSAtsushi Murai case ST_STOPPING: 600af57ed9fSAtsushi Murai pfree(bp); 601af57ed9fSAtsushi Murai return; 602af57ed9fSAtsushi Murai } 603af57ed9fSAtsushi Murai 60453c9f6c0SAtsushi Murai (fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REJ); 605af57ed9fSAtsushi Murai 606af57ed9fSAtsushi Murai switch (fp->state) { 607af57ed9fSAtsushi Murai case ST_REQSENT: 608af57ed9fSAtsushi Murai case ST_ACKSENT: 609af57ed9fSAtsushi Murai FsmInitRestartCounter(fp); 610af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 611af57ed9fSAtsushi Murai break; 612af57ed9fSAtsushi Murai case ST_OPENED: 613af57ed9fSAtsushi Murai (fp->LayerDown) (fp); 614af57ed9fSAtsushi Murai /* Fall down */ 615af57ed9fSAtsushi Murai case ST_ACKRCVD: 616af57ed9fSAtsushi Murai FsmSendConfigReq(fp); 617af57ed9fSAtsushi Murai NewState(fp, ST_REQSENT); 618af57ed9fSAtsushi Murai break; 619af57ed9fSAtsushi Murai } 620af57ed9fSAtsushi Murai pfree(bp); 621af57ed9fSAtsushi Murai } 622af57ed9fSAtsushi Murai 62375240ed1SBrian Somers static void 624944f7098SBrian Somers FsmRecvCodeRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 625af57ed9fSAtsushi Murai { 626cb611434SBrian Somers LogPrintf(fp->LogLevel, "RecvCodeRej\n"); 627af57ed9fSAtsushi Murai pfree(bp); 628af57ed9fSAtsushi Murai } 629af57ed9fSAtsushi Murai 63075240ed1SBrian Somers static void 631944f7098SBrian Somers FsmRecvProtoRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 632af57ed9fSAtsushi Murai { 633af57ed9fSAtsushi Murai u_short *sp, proto; 634af57ed9fSAtsushi Murai 635af57ed9fSAtsushi Murai sp = (u_short *) MBUF_CTOP(bp); 636af57ed9fSAtsushi Murai proto = ntohs(*sp); 637cb611434SBrian Somers LogPrintf(fp->LogLevel, "-- Protocol (%04x) was rejected.\n", proto); 638af57ed9fSAtsushi Murai 639af57ed9fSAtsushi Murai switch (proto) { 640af57ed9fSAtsushi Murai case PROTO_LQR: 641af57ed9fSAtsushi Murai StopLqr(LQM_LQR); 642af57ed9fSAtsushi Murai break; 643af57ed9fSAtsushi Murai case PROTO_CCP: 644af57ed9fSAtsushi Murai fp = &CcpFsm; 645af57ed9fSAtsushi Murai (fp->LayerFinish) (fp); 646af57ed9fSAtsushi Murai switch (fp->state) { 647af57ed9fSAtsushi Murai case ST_CLOSED: 648af57ed9fSAtsushi Murai case ST_CLOSING: 649af57ed9fSAtsushi Murai NewState(fp, ST_CLOSED); 650af57ed9fSAtsushi Murai default: 651af57ed9fSAtsushi Murai NewState(fp, ST_STOPPED); 652af57ed9fSAtsushi Murai break; 653af57ed9fSAtsushi Murai } 654af57ed9fSAtsushi Murai break; 655af57ed9fSAtsushi Murai } 656af57ed9fSAtsushi Murai pfree(bp); 657af57ed9fSAtsushi Murai } 658af57ed9fSAtsushi Murai 65975240ed1SBrian Somers static void 660944f7098SBrian Somers FsmRecvEchoReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 661af57ed9fSAtsushi Murai { 662af57ed9fSAtsushi Murai u_char *cp; 663af57ed9fSAtsushi Murai u_long *lp, magic; 664af57ed9fSAtsushi Murai 665af57ed9fSAtsushi Murai cp = MBUF_CTOP(bp); 666af57ed9fSAtsushi Murai lp = (u_long *) cp; 667af57ed9fSAtsushi Murai magic = ntohl(*lp); 668af57ed9fSAtsushi Murai if (magic != LcpInfo.his_magic) { 669927145beSBrian Somers LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n"); 670af57ed9fSAtsushi Murai /* XXX: We should send terminate request */ 671af57ed9fSAtsushi Murai } 672af57ed9fSAtsushi Murai if (fp->state == ST_OPENED) { 673af57ed9fSAtsushi Murai *lp = htonl(LcpInfo.want_magic); /* Insert local magic number */ 674cb611434SBrian Somers LogPrintf(fp->LogLevel, "SendEchoRep(%s)\n", StateNames[fp->state]); 675af57ed9fSAtsushi Murai FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp)); 676af57ed9fSAtsushi Murai } 677af57ed9fSAtsushi Murai pfree(bp); 678af57ed9fSAtsushi Murai } 679af57ed9fSAtsushi Murai 68075240ed1SBrian Somers static void 681944f7098SBrian Somers FsmRecvEchoRep(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 682af57ed9fSAtsushi Murai { 683af57ed9fSAtsushi Murai u_long *lp, magic; 684af57ed9fSAtsushi Murai 685af57ed9fSAtsushi Murai lp = (u_long *) MBUF_CTOP(bp); 686af57ed9fSAtsushi Murai magic = ntohl(*lp); 68785c59f05SJoerg Wunsch /* 68885c59f05SJoerg Wunsch * Tolerate echo replies with either magic number 68985c59f05SJoerg Wunsch */ 69085c59f05SJoerg Wunsch if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) { 691927145beSBrian Somers LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n", 692af57ed9fSAtsushi Murai LcpInfo.his_magic, magic); 693944f7098SBrian Somers 694af57ed9fSAtsushi Murai /* 695944f7098SBrian Somers * XXX: We should send terminate request. But poor implementation may die 696944f7098SBrian Somers * as a result. 697af57ed9fSAtsushi Murai */ 698af57ed9fSAtsushi Murai } 699af57ed9fSAtsushi Murai RecvEchoLqr(bp); 700af57ed9fSAtsushi Murai pfree(bp); 701af57ed9fSAtsushi Murai } 702af57ed9fSAtsushi Murai 70375240ed1SBrian Somers static void 704944f7098SBrian Somers FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 705af57ed9fSAtsushi Murai { 706cb611434SBrian Somers LogPrintf(fp->LogLevel, "RecvDiscReq\n"); 707af57ed9fSAtsushi Murai pfree(bp); 708af57ed9fSAtsushi Murai } 709af57ed9fSAtsushi Murai 71075240ed1SBrian Somers static void 711944f7098SBrian Somers FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 712af57ed9fSAtsushi Murai { 713cb611434SBrian Somers LogPrintf(fp->LogLevel, "RecvIdent\n"); 714af57ed9fSAtsushi Murai pfree(bp); 715af57ed9fSAtsushi Murai } 716af57ed9fSAtsushi Murai 71775240ed1SBrian Somers static void 718944f7098SBrian Somers FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 719af57ed9fSAtsushi Murai { 720cb611434SBrian Somers LogPrintf(fp->LogLevel, "RecvTimeRemain\n"); 721af57ed9fSAtsushi Murai pfree(bp); 722af57ed9fSAtsushi Murai } 723af57ed9fSAtsushi Murai 72475240ed1SBrian Somers static void 725944f7098SBrian Somers FsmRecvResetReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 726af57ed9fSAtsushi Murai { 72798baf7c8SBrian Somers LogPrintf(fp->LogLevel, "RecvResetReq(%d)\n", lhp->id); 728af57ed9fSAtsushi Murai CcpRecvResetReq(fp); 72998baf7c8SBrian Somers /* 73098baf7c8SBrian Somers * All sendable compressed packets are queued in the PRI_NORMAL modem 73198baf7c8SBrian Somers * output queue.... dump 'em to the priority queue so that they arrive 73298baf7c8SBrian Somers * at the peer before our ResetAck. 73398baf7c8SBrian Somers */ 73498baf7c8SBrian Somers SequenceQueues(); 73598baf7c8SBrian Somers LogPrintf(fp->LogLevel, "SendResetAck(%d)\n", lhp->id); 73698baf7c8SBrian Somers FsmOutput(fp, CODE_RESETACK, lhp->id, NULL, 0); 737af57ed9fSAtsushi Murai pfree(bp); 738af57ed9fSAtsushi Murai } 739af57ed9fSAtsushi Murai 74075240ed1SBrian Somers static void 741944f7098SBrian Somers FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 742af57ed9fSAtsushi Murai { 74398baf7c8SBrian Somers LogPrintf(fp->LogLevel, "RecvResetAck(%d)\n", lhp->id); 74498baf7c8SBrian Somers CcpResetInput(lhp->id); 745af57ed9fSAtsushi Murai fp->reqid++; 746af57ed9fSAtsushi Murai pfree(bp); 747af57ed9fSAtsushi Murai } 748af57ed9fSAtsushi Murai 7490053cc58SBrian Somers static const struct fsmcodedesc FsmCodes[] = { 750af57ed9fSAtsushi Murai {FsmRecvConfigReq, "Configure Request",}, 751af57ed9fSAtsushi Murai {FsmRecvConfigAck, "Configure Ack",}, 752af57ed9fSAtsushi Murai {FsmRecvConfigNak, "Configure Nak",}, 753af57ed9fSAtsushi Murai {FsmRecvConfigRej, "Configure Reject",}, 754af57ed9fSAtsushi Murai {FsmRecvTermReq, "Terminate Request",}, 755af57ed9fSAtsushi Murai {FsmRecvTermAck, "Terminate Ack",}, 756af57ed9fSAtsushi Murai {FsmRecvCodeRej, "Code Reject",}, 757af57ed9fSAtsushi Murai {FsmRecvProtoRej, "Protocol Reject",}, 758af57ed9fSAtsushi Murai {FsmRecvEchoReq, "Echo Request",}, 759af57ed9fSAtsushi Murai {FsmRecvEchoRep, "Echo Reply",}, 760af57ed9fSAtsushi Murai {FsmRecvDiscReq, "Discard Request",}, 761af57ed9fSAtsushi Murai {FsmRecvIdent, "Ident",}, 762af57ed9fSAtsushi Murai {FsmRecvTimeRemain, "Time Remain",}, 763af57ed9fSAtsushi Murai {FsmRecvResetReq, "Reset Request",}, 764af57ed9fSAtsushi Murai {FsmRecvResetAck, "Reset Ack",}, 765af57ed9fSAtsushi Murai }; 766af57ed9fSAtsushi Murai 767af57ed9fSAtsushi Murai void 768944f7098SBrian Somers FsmInput(struct fsm * fp, struct mbuf * bp) 769af57ed9fSAtsushi Murai { 770af57ed9fSAtsushi Murai int len; 771af57ed9fSAtsushi Murai struct fsmheader *lhp; 7720053cc58SBrian Somers const struct fsmcodedesc *codep; 773af57ed9fSAtsushi Murai 774af57ed9fSAtsushi Murai len = plength(bp); 775af57ed9fSAtsushi Murai if (len < sizeof(struct fsmheader)) { 776af57ed9fSAtsushi Murai pfree(bp); 777af57ed9fSAtsushi Murai return; 778af57ed9fSAtsushi Murai } 779af57ed9fSAtsushi Murai lhp = (struct fsmheader *) MBUF_CTOP(bp); 780af57ed9fSAtsushi Murai if (lhp->code == 0 || lhp->code > fp->max_code) { 781af57ed9fSAtsushi Murai pfree(bp); /* XXX: Should send code reject */ 782af57ed9fSAtsushi Murai return; 783af57ed9fSAtsushi Murai } 784af57ed9fSAtsushi Murai bp->offset += sizeof(struct fsmheader); 785af57ed9fSAtsushi Murai bp->cnt -= sizeof(struct fsmheader); 786af57ed9fSAtsushi Murai 787af57ed9fSAtsushi Murai codep = FsmCodes + lhp->code - 1; 788cb611434SBrian Somers LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n", 789927145beSBrian Somers codep->name, lhp->id, StateNames[fp->state], fp->state); 790927145beSBrian Somers if (LogIsKept(LogDEBUG)) 791af57ed9fSAtsushi Murai LogMemory(); 792af57ed9fSAtsushi Murai (codep->action) (fp, lhp, bp); 793927145beSBrian Somers if (LogIsKept(LogDEBUG)) 794af57ed9fSAtsushi Murai LogMemory(); 795af57ed9fSAtsushi Murai } 796