fsm.c revision 37210
1139823Simp/* 21541Srgrimes * PPP Finite State Machine for LCP/IPCP 3180305Srwatson * 4180305Srwatson * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 51541Srgrimes * 61541Srgrimes * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms are permitted 91541Srgrimes * provided that the above copyright notice and this paragraph are 101541Srgrimes * duplicated in all such forms and that any documentation, 111541Srgrimes * advertising materials, and other materials related to such 121541Srgrimes * distribution and use acknowledge that the software was developed 131541Srgrimes * by the Internet Initiative Japan, Inc. The name of the 141541Srgrimes * IIJ may not be used to endorse or promote products derived 151541Srgrimes * from this software without specific prior written permission. 161541Srgrimes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 171541Srgrimes * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 181541Srgrimes * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 191541Srgrimes * 201541Srgrimes * $Id: fsm.c,v 1.33 1998/06/25 22:33:20 brian Exp $ 211541Srgrimes * 221541Srgrimes * TODO: 231541Srgrimes */ 241541Srgrimes 251541Srgrimes#include <sys/types.h> 261541Srgrimes#include <netinet/in.h> 271541Srgrimes#include <netinet/in_systm.h> 281541Srgrimes#include <netinet/ip.h> 291541Srgrimes#include <sys/un.h> 301541Srgrimes 3150477Speter#include <string.h> 321541Srgrimes#include <termios.h> 331541Srgrimes 341541Srgrimes#include "mbuf.h" 3596972Stanimura#include "log.h" 36130387Srwatson#include "defs.h" 37180390Srwatson#include "timer.h" 3829024Sbde#include "fsm.h" 39130387Srwatson#include "iplist.h" 4096972Stanimura#include "lqr.h" 411541Srgrimes#include "hdlc.h" 421541Srgrimes#include "throughput.h" 43180390Srwatson#include "slcompress.h" 4497093Sbde#include "ipcp.h" 451541Srgrimes#include "filter.h" 461541Srgrimes#include "descriptor.h" 471541Srgrimes#include "lcp.h" 481541Srgrimes#include "ccp.h" 498876Srgrimes#include "link.h" 501541Srgrimes#include "mp.h" 511541Srgrimes#include "bundle.h" 521541Srgrimes#include "async.h" 531541Srgrimes#include "physical.h" 541541Srgrimes#include "lcpproto.h" 551541Srgrimes 561541Srgrimesstatic void FsmSendConfigReq(struct fsm *); 57130514Srwatsonstatic void FsmSendTerminateReq(struct fsm *); 5824936Sphkstatic void FsmInitRestartCounter(struct fsm *); 5924936Sphk 60180390Srwatsontypedef void (recvfn)(struct fsm *, struct fsmheader *, struct mbuf *); 611541Srgrimesstatic recvfn FsmRecvConfigReq, FsmRecvConfigAck, FsmRecvConfigNak, 62180390Srwatson FsmRecvConfigRej, FsmRecvTermReq, FsmRecvTermAck, 63180390Srwatson FsmRecvCodeRej, FsmRecvProtoRej, FsmRecvEchoReq, 64180390Srwatson FsmRecvEchoRep, FsmRecvDiscReq, FsmRecvIdent, 65180390Srwatson FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck; 66180390Srwatson 67180390Srwatsonstatic const struct fsmcodedesc { 68180390Srwatson recvfn *recv; 69180390Srwatson unsigned check_reqid : 1; 701541Srgrimes unsigned inc_reqid : 1; 71180305Srwatson const char *name; 72180305Srwatson} FsmCodes[] = { 731541Srgrimes { FsmRecvConfigReq, 0, 0, "ConfigReq" }, 741541Srgrimes { FsmRecvConfigAck, 1, 1, "ConfigAck" }, 75180305Srwatson { FsmRecvConfigNak, 1, 1, "ConfigNak" }, 761541Srgrimes { FsmRecvConfigRej, 1, 1, "ConfigRej" }, 77180305Srwatson { FsmRecvTermReq, 0, 0, "TerminateReq" }, 781541Srgrimes { FsmRecvTermAck, 1, 1, "TerminateAck" }, 791541Srgrimes { FsmRecvCodeRej, 0, 0, "CodeRej" }, 801541Srgrimes { FsmRecvProtoRej, 0, 0, "ProtocolRej" }, 81180391Srwatson { FsmRecvEchoReq, 0, 0, "EchoRequest" }, 82180391Srwatson { FsmRecvEchoRep, 0, 0, "EchoReply" }, 83180391Srwatson { FsmRecvDiscReq, 0, 0, "DiscardReq" }, 84180391Srwatson { FsmRecvIdent, 0, 0, "Ident" }, 851541Srgrimes { FsmRecvTimeRemain,0, 0, "TimeRemain" }, 86180391Srwatson { FsmRecvResetReq, 0, 0, "ResetReqt" }, 87180391Srwatson { FsmRecvResetAck, 0, 1, "ResetAck" } 883443Sphk}; 893443Sphk 901541Srgrimesstatic const char * 911541SrgrimesCode2Nam(u_int code) 921541Srgrimes{ 931541Srgrimes if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0]) 94130514Srwatson return "Unknown"; 9524936Sphk return FsmCodes[code-1].name; 96130514Srwatson} 971541Srgrimes 981541Srgrimesconst char * 991541SrgrimesState2Nam(u_int state) 1001541Srgrimes{ 101180305Srwatson static const char *StateNames[] = { 1021541Srgrimes "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 1031541Srgrimes "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened", 104180305Srwatson }; 1051541Srgrimes 1061541Srgrimes if (state >= sizeof StateNames / sizeof StateNames[0]) 1071541Srgrimes return "unknown"; 108157370Srwatson return StateNames[state]; 109157370Srwatson} 110157370Srwatson 111140775Srwatsonstatic void 11224936SphkStoppedTimeout(void *v) 113140775Srwatson{ 1141541Srgrimes struct fsm *fp = (struct fsm *)v; 1151541Srgrimes 116 log_Printf(fp->LogLevel, "%s: Stopped timer expired\n", fp->link->name); 117 if (fp->OpenTimer.state == TIMER_RUNNING) { 118 log_Printf(LogWARN, "%s: %s: aborting open delay due to stopped timer\n", 119 fp->link->name, fp->name); 120 timer_Stop(&fp->OpenTimer); 121 } 122 if (fp->state == ST_STOPPED) 123 fsm2initial(fp); 124} 125 126void 127fsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode, 128 int maxcode, int maxcfg, int LogLevel, struct bundle *bundle, 129 struct link *l, const struct fsm_parent *parent, 130 struct fsm_callbacks *fn, const char *timer_names[3]) 131{ 132 fp->name = name; 133 fp->proto = proto; 134 fp->min_code = mincode; 135 fp->max_code = maxcode; 136 fp->state = fp->min_code > CODE_TERMACK ? ST_OPENED : ST_INITIAL; 137 fp->reqid = 1; 138 fp->restart = 1; 139 fp->maxconfig = maxcfg; 140 memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer); 141 memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer); 142 memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer); 143 fp->LogLevel = LogLevel; 144 fp->link = l; 145 fp->bundle = bundle; 146 fp->parent = parent; 147 fp->fn = fn; 148 fp->FsmTimer.name = timer_names[0]; 149 fp->OpenTimer.name = timer_names[1]; 150 fp->StoppedTimer.name = timer_names[2]; 151} 152 153static void 154NewState(struct fsm * fp, int new) 155{ 156 log_Printf(fp->LogLevel, "%s: State change %s --> %s\n", 157 fp->link->name, State2Nam(fp->state), State2Nam(new)); 158 if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING) 159 timer_Stop(&fp->StoppedTimer); 160 fp->state = new; 161 if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) { 162 timer_Stop(&fp->FsmTimer); 163 if (new == ST_STOPPED && fp->StoppedTimer.load) { 164 timer_Stop(&fp->StoppedTimer); 165 fp->StoppedTimer.func = StoppedTimeout; 166 fp->StoppedTimer.arg = (void *) fp; 167 timer_Start(&fp->StoppedTimer); 168 } 169 } 170} 171 172void 173fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count) 174{ 175 int plen; 176 struct fsmheader lh; 177 struct mbuf *bp; 178 179 if (log_IsKept(fp->LogLevel)) { 180 log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n", 181 fp->link->name, Code2Nam(code), id, State2Nam(fp->state)); 182 switch (code) { 183 case CODE_CONFIGREQ: 184 case CODE_CONFIGACK: 185 case CODE_CONFIGREJ: 186 case CODE_CONFIGNAK: 187 (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL); 188 if (count < sizeof(struct fsmconfig)) 189 log_Printf(fp->LogLevel, " [EMPTY]\n"); 190 break; 191 } 192 } 193 194 plen = sizeof(struct fsmheader) + count; 195 lh.code = code; 196 lh.id = id; 197 lh.length = htons(plen); 198 bp = mbuf_Alloc(plen, MB_FSM); 199 memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 200 if (count) 201 memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count); 202 log_DumpBp(LogDEBUG, "fsm_Output", bp); 203 hdlc_Output(fp->link, PRI_LINK, fp->proto, bp); 204} 205 206static void 207FsmOpenNow(void *v) 208{ 209 struct fsm *fp = (struct fsm *)v; 210 211 timer_Stop(&fp->OpenTimer); 212 if (fp->state <= ST_STOPPED) { 213 if (fp->state != ST_STARTING) { 214 /* 215 * In practice, we're only here in ST_STOPPED (when delaying the 216 * first config request) or ST_CLOSED (when openmode == 0). 217 * 218 * The ST_STOPPED bit is breaking the RFC already :-( 219 * 220 * According to the RFC (1661) state transition table, a TLS isn't 221 * required for an Open event when state == Closed, but the RFC 222 * must be wrong as TLS hasn't yet been called (since the last TLF) 223 * ie, Initial gets an `Up' event, Closing gets a RTA etc. 224 */ 225 (*fp->fn->LayerStart)(fp); 226 (*fp->parent->LayerStart)(fp->parent->object, fp); 227 } 228 FsmInitRestartCounter(fp); 229 FsmSendConfigReq(fp); 230 NewState(fp, ST_REQSENT); 231 } 232} 233 234void 235fsm_Open(struct fsm * fp) 236{ 237 switch (fp->state) { 238 case ST_INITIAL: 239 NewState(fp, ST_STARTING); 240 (*fp->fn->LayerStart)(fp); 241 (*fp->parent->LayerStart)(fp->parent->object, fp); 242 break; 243 case ST_CLOSED: 244 if (fp->open_mode == OPEN_PASSIVE) { 245 NewState(fp, ST_STOPPED); /* XXX: This is a hack ! */ 246 } else if (fp->open_mode > 0) { 247 if (fp->open_mode > 1) 248 log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n", 249 fp->link->name, fp->open_mode); 250 NewState(fp, ST_STOPPED); /* XXX: This is a not-so-bad hack ! */ 251 timer_Stop(&fp->OpenTimer); 252 fp->OpenTimer.load = fp->open_mode * SECTICKS; 253 fp->OpenTimer.func = FsmOpenNow; 254 fp->OpenTimer.arg = (void *)fp; 255 timer_Start(&fp->OpenTimer); 256 } else 257 FsmOpenNow(fp); 258 break; 259 case ST_STOPPED: /* XXX: restart option */ 260 case ST_REQSENT: 261 case ST_ACKRCVD: 262 case ST_ACKSENT: 263 case ST_OPENED: /* XXX: restart option */ 264 break; 265 case ST_CLOSING: /* XXX: restart option */ 266 case ST_STOPPING: /* XXX: restart option */ 267 NewState(fp, ST_STOPPING); 268 break; 269 } 270} 271 272void 273fsm_Up(struct fsm * fp) 274{ 275 switch (fp->state) { 276 case ST_INITIAL: 277 log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n", 278 fp->link->name); 279 NewState(fp, ST_CLOSED); 280 break; 281 case ST_STARTING: 282 FsmInitRestartCounter(fp); 283 FsmSendConfigReq(fp); 284 NewState(fp, ST_REQSENT); 285 break; 286 default: 287 log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n", 288 fp->link->name, State2Nam(fp->state)); 289 break; 290 } 291} 292 293void 294fsm_Down(struct fsm *fp) 295{ 296 switch (fp->state) { 297 case ST_CLOSED: 298 NewState(fp, ST_INITIAL); 299 break; 300 case ST_CLOSING: 301 (*fp->fn->LayerFinish)(fp); 302 NewState(fp, ST_INITIAL); 303 (*fp->parent->LayerFinish)(fp->parent->object, fp); 304 break; 305 case ST_STOPPED: 306 NewState(fp, ST_STARTING); 307 (*fp->fn->LayerStart)(fp); 308 (*fp->parent->LayerStart)(fp->parent->object, fp); 309 break; 310 case ST_STOPPING: 311 case ST_REQSENT: 312 case ST_ACKRCVD: 313 case ST_ACKSENT: 314 NewState(fp, ST_STARTING); 315 break; 316 case ST_OPENED: 317 (*fp->fn->LayerDown)(fp); 318 NewState(fp, ST_STARTING); 319 (*fp->parent->LayerDown)(fp->parent->object, fp); 320 break; 321 } 322} 323 324void 325fsm_Close(struct fsm *fp) 326{ 327 switch (fp->state) { 328 case ST_STARTING: 329 (*fp->fn->LayerFinish)(fp); 330 NewState(fp, ST_INITIAL); 331 (*fp->parent->LayerFinish)(fp->parent->object, fp); 332 break; 333 case ST_STOPPED: 334 NewState(fp, ST_CLOSED); 335 break; 336 case ST_STOPPING: 337 NewState(fp, ST_CLOSING); 338 break; 339 case ST_OPENED: 340 (*fp->fn->LayerDown)(fp); 341 FsmInitRestartCounter(fp); 342 FsmSendTerminateReq(fp); 343 NewState(fp, ST_CLOSING); 344 (*fp->parent->LayerDown)(fp->parent->object, fp); 345 break; 346 case ST_REQSENT: 347 case ST_ACKRCVD: 348 case ST_ACKSENT: 349 FsmInitRestartCounter(fp); 350 FsmSendTerminateReq(fp); 351 NewState(fp, ST_CLOSING); 352 break; 353 } 354} 355 356/* 357 * Send functions 358 */ 359static void 360FsmSendConfigReq(struct fsm * fp) 361{ 362 if (--fp->maxconfig > 0) { 363 (*fp->fn->SendConfigReq)(fp); 364 timer_Start(&fp->FsmTimer); /* Start restart timer */ 365 fp->restart--; /* Decrement restart counter */ 366 } else { 367 fsm_Close(fp); 368 } 369} 370 371static void 372FsmSendTerminateReq(struct fsm *fp) 373{ 374 fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0); 375 (*fp->fn->SentTerminateReq)(fp); 376 timer_Start(&fp->FsmTimer); /* Start restart timer */ 377 fp->restart--; /* Decrement restart counter */ 378} 379 380/* 381 * Timeout actions 382 */ 383static void 384FsmTimeout(void *v) 385{ 386 struct fsm *fp = (struct fsm *)v; 387 388 if (fp->restart) { 389 switch (fp->state) { 390 case ST_CLOSING: 391 case ST_STOPPING: 392 FsmSendTerminateReq(fp); 393 break; 394 case ST_REQSENT: 395 case ST_ACKSENT: 396 FsmSendConfigReq(fp); 397 break; 398 case ST_ACKRCVD: 399 FsmSendConfigReq(fp); 400 NewState(fp, ST_REQSENT); 401 break; 402 } 403 timer_Start(&fp->FsmTimer); 404 } else { 405 switch (fp->state) { 406 case ST_CLOSING: 407 (*fp->fn->LayerFinish)(fp); 408 NewState(fp, ST_CLOSED); 409 (*fp->parent->LayerFinish)(fp->parent->object, fp); 410 break; 411 case ST_STOPPING: 412 (*fp->fn->LayerFinish)(fp); 413 NewState(fp, ST_STOPPED); 414 (*fp->parent->LayerFinish)(fp->parent->object, fp); 415 break; 416 case ST_REQSENT: /* XXX: 3p */ 417 case ST_ACKSENT: 418 case ST_ACKRCVD: 419 (*fp->fn->LayerFinish)(fp); 420 NewState(fp, ST_STOPPED); 421 (*fp->parent->LayerFinish)(fp->parent->object, fp); 422 break; 423 } 424 } 425} 426 427static void 428FsmInitRestartCounter(struct fsm * fp) 429{ 430 timer_Stop(&fp->FsmTimer); 431 fp->FsmTimer.func = FsmTimeout; 432 fp->FsmTimer.arg = (void *) fp; 433 (*fp->fn->InitRestartCounter)(fp); 434} 435 436/* 437 * Actions when receive packets 438 */ 439static void 440FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 441/* RCR */ 442{ 443 struct fsm_decode dec; 444 int plen, flen; 445 int ackaction = 0; 446 447 plen = mbuf_Length(bp); 448 flen = ntohs(lhp->length) - sizeof *lhp; 449 if (plen < flen) { 450 log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n", 451 fp->link->name, plen, flen); 452 mbuf_Free(bp); 453 return; 454 } 455 456 /* 457 * Check and process easy case 458 */ 459 switch (fp->state) { 460 case ST_INITIAL: 461 case ST_STARTING: 462 log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n", 463 fp->link->name, State2Nam(fp->state)); 464 mbuf_Free(bp); 465 return; 466 case ST_CLOSED: 467 (*fp->fn->SendTerminateAck)(fp, lhp->id); 468 mbuf_Free(bp); 469 return; 470 case ST_CLOSING: 471 log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n", 472 fp->link->name, State2Nam(fp->state)); 473 case ST_STOPPING: 474 mbuf_Free(bp); 475 return; 476 } 477 478 dec.ackend = dec.ack; 479 dec.nakend = dec.nak; 480 dec.rejend = dec.rej; 481 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec); 482 if (flen < sizeof(struct fsmconfig)) 483 log_Printf(fp->LogLevel, " [EMPTY]\n"); 484 485 if (dec.nakend == dec.nak && dec.rejend == dec.rej) 486 ackaction = 1; 487 488 switch (fp->state) { 489 case ST_OPENED: 490 (*fp->fn->LayerDown)(fp); 491 FsmSendConfigReq(fp); 492 (*fp->parent->LayerDown)(fp->parent->object, fp); 493 break; 494 case ST_STOPPED: 495 FsmInitRestartCounter(fp); 496 FsmSendConfigReq(fp); 497 break; 498 } 499 500 if (dec.rejend != dec.rej) 501 fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej); 502 if (dec.nakend != dec.nak) 503 fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak); 504 if (ackaction) 505 fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack); 506 507 switch (fp->state) { 508 case ST_OPENED: 509 case ST_STOPPED: 510 if (ackaction) 511 NewState(fp, ST_ACKSENT); 512 else 513 NewState(fp, ST_REQSENT); 514 break; 515 case ST_REQSENT: 516 if (ackaction) 517 NewState(fp, ST_ACKSENT); 518 break; 519 case ST_ACKRCVD: 520 if (ackaction) { 521 NewState(fp, ST_OPENED); 522 if ((*fp->fn->LayerUp)(fp)) 523 (*fp->parent->LayerUp)(fp->parent->object, fp); 524 else { 525 (*fp->fn->LayerDown)(fp); 526 FsmInitRestartCounter(fp); 527 FsmSendTerminateReq(fp); 528 NewState(fp, ST_CLOSING); 529 } 530 } 531 break; 532 case ST_ACKSENT: 533 if (!ackaction) 534 NewState(fp, ST_REQSENT); 535 break; 536 } 537 mbuf_Free(bp); 538} 539 540static void 541FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 542/* RCA */ 543{ 544 switch (fp->state) { 545 case ST_CLOSED: 546 case ST_STOPPED: 547 (*fp->fn->SendTerminateAck)(fp, lhp->id); 548 break; 549 case ST_CLOSING: 550 case ST_STOPPING: 551 break; 552 case ST_REQSENT: 553 FsmInitRestartCounter(fp); 554 NewState(fp, ST_ACKRCVD); 555 break; 556 case ST_ACKRCVD: 557 FsmSendConfigReq(fp); 558 NewState(fp, ST_REQSENT); 559 break; 560 case ST_ACKSENT: 561 FsmInitRestartCounter(fp); 562 NewState(fp, ST_OPENED); 563 if ((*fp->fn->LayerUp)(fp)) 564 (*fp->parent->LayerUp)(fp->parent->object, fp); 565 else { 566 (*fp->fn->LayerDown)(fp); 567 FsmInitRestartCounter(fp); 568 FsmSendTerminateReq(fp); 569 NewState(fp, ST_CLOSING); 570 } 571 break; 572 case ST_OPENED: 573 (*fp->fn->LayerDown)(fp); 574 FsmSendConfigReq(fp); 575 NewState(fp, ST_REQSENT); 576 (*fp->parent->LayerDown)(fp->parent->object, fp); 577 break; 578 } 579 mbuf_Free(bp); 580} 581 582static void 583FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 584/* RCN */ 585{ 586 struct fsm_decode dec; 587 int plen, flen; 588 589 plen = mbuf_Length(bp); 590 flen = ntohs(lhp->length) - sizeof *lhp; 591 if (plen < flen) { 592 mbuf_Free(bp); 593 return; 594 } 595 596 /* 597 * Check and process easy case 598 */ 599 switch (fp->state) { 600 case ST_INITIAL: 601 case ST_STARTING: 602 log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n", 603 fp->link->name, State2Nam(fp->state)); 604 mbuf_Free(bp); 605 return; 606 case ST_CLOSED: 607 case ST_STOPPED: 608 (*fp->fn->SendTerminateAck)(fp, lhp->id); 609 mbuf_Free(bp); 610 return; 611 case ST_CLOSING: 612 case ST_STOPPING: 613 mbuf_Free(bp); 614 return; 615 } 616 617 dec.ackend = dec.ack; 618 dec.nakend = dec.nak; 619 dec.rejend = dec.rej; 620 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec); 621 if (flen < sizeof(struct fsmconfig)) 622 log_Printf(fp->LogLevel, " [EMPTY]\n"); 623 624 switch (fp->state) { 625 case ST_REQSENT: 626 case ST_ACKSENT: 627 FsmInitRestartCounter(fp); 628 FsmSendConfigReq(fp); 629 break; 630 case ST_OPENED: 631 (*fp->fn->LayerDown)(fp); 632 FsmSendConfigReq(fp); 633 NewState(fp, ST_REQSENT); 634 (*fp->parent->LayerDown)(fp->parent->object, fp); 635 break; 636 case ST_ACKRCVD: 637 FsmSendConfigReq(fp); 638 NewState(fp, ST_REQSENT); 639 break; 640 } 641 642 mbuf_Free(bp); 643} 644 645static void 646FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 647/* RTR */ 648{ 649 switch (fp->state) { 650 case ST_INITIAL: 651 case ST_STARTING: 652 log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n", 653 fp->link->name, State2Nam(fp->state)); 654 break; 655 case ST_CLOSED: 656 case ST_STOPPED: 657 case ST_CLOSING: 658 case ST_STOPPING: 659 case ST_REQSENT: 660 (*fp->fn->SendTerminateAck)(fp, lhp->id); 661 break; 662 case ST_ACKRCVD: 663 case ST_ACKSENT: 664 (*fp->fn->SendTerminateAck)(fp, lhp->id); 665 NewState(fp, ST_REQSENT); 666 break; 667 case ST_OPENED: 668 (*fp->fn->LayerDown)(fp); 669 (*fp->fn->SendTerminateAck)(fp, lhp->id); 670 FsmInitRestartCounter(fp); 671 timer_Start(&fp->FsmTimer); /* Start restart timer */ 672 fp->restart = 0; 673 NewState(fp, ST_STOPPING); 674 (*fp->parent->LayerDown)(fp->parent->object, fp); 675 break; 676 } 677 mbuf_Free(bp); 678} 679 680static void 681FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 682/* RTA */ 683{ 684 switch (fp->state) { 685 case ST_CLOSING: 686 (*fp->fn->LayerFinish)(fp); 687 NewState(fp, ST_CLOSED); 688 (*fp->parent->LayerFinish)(fp->parent->object, fp); 689 break; 690 case ST_STOPPING: 691 (*fp->fn->LayerFinish)(fp); 692 NewState(fp, ST_STOPPED); 693 (*fp->parent->LayerFinish)(fp->parent->object, fp); 694 break; 695 case ST_ACKRCVD: 696 NewState(fp, ST_REQSENT); 697 break; 698 case ST_OPENED: 699 (*fp->fn->LayerDown)(fp); 700 FsmSendConfigReq(fp); 701 NewState(fp, ST_REQSENT); 702 (*fp->parent->LayerDown)(fp->parent->object, fp); 703 break; 704 } 705 mbuf_Free(bp); 706} 707 708static void 709FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 710/* RCJ */ 711{ 712 struct fsm_decode dec; 713 int plen, flen; 714 715 plen = mbuf_Length(bp); 716 flen = ntohs(lhp->length) - sizeof *lhp; 717 if (plen < flen) { 718 mbuf_Free(bp); 719 return; 720 } 721 722 /* 723 * Check and process easy case 724 */ 725 switch (fp->state) { 726 case ST_INITIAL: 727 case ST_STARTING: 728 log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n", 729 fp->link->name, State2Nam(fp->state)); 730 mbuf_Free(bp); 731 return; 732 case ST_CLOSED: 733 case ST_STOPPED: 734 (*fp->fn->SendTerminateAck)(fp, lhp->id); 735 mbuf_Free(bp); 736 return; 737 case ST_CLOSING: 738 case ST_STOPPING: 739 mbuf_Free(bp); 740 return; 741 } 742 743 dec.ackend = dec.ack; 744 dec.nakend = dec.nak; 745 dec.rejend = dec.rej; 746 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec); 747 if (flen < sizeof(struct fsmconfig)) 748 log_Printf(fp->LogLevel, " [EMPTY]\n"); 749 750 switch (fp->state) { 751 case ST_REQSENT: 752 case ST_ACKSENT: 753 FsmInitRestartCounter(fp); 754 FsmSendConfigReq(fp); 755 break; 756 case ST_OPENED: 757 (*fp->fn->LayerDown)(fp); 758 FsmSendConfigReq(fp); 759 NewState(fp, ST_REQSENT); 760 (*fp->parent->LayerDown)(fp->parent->object, fp); 761 break; 762 case ST_ACKRCVD: 763 FsmSendConfigReq(fp); 764 NewState(fp, ST_REQSENT); 765 break; 766 } 767 mbuf_Free(bp); 768} 769 770static void 771FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 772{ 773 mbuf_Free(bp); 774} 775 776static void 777FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 778{ 779 struct physical *p = link2physical(fp->link); 780 u_short *sp, proto; 781 782 sp = (u_short *)MBUF_CTOP(bp); 783 proto = ntohs(*sp); 784 log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n", 785 fp->link->name, proto, hdlc_Protocol2Nam(proto)); 786 787 switch (proto) { 788 case PROTO_LQR: 789 if (p) 790 lqr_Stop(p, LQM_LQR); 791 else 792 log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n", 793 fp->link->name); 794 break; 795 case PROTO_CCP: 796 if (fp->proto == PROTO_LCP) { 797 fp = &fp->link->ccp.fsm; 798 (*fp->fn->LayerFinish)(fp); 799 switch (fp->state) { 800 case ST_CLOSED: 801 case ST_CLOSING: 802 NewState(fp, ST_CLOSED); 803 default: 804 NewState(fp, ST_STOPPED); 805 break; 806 } 807 (*fp->parent->LayerFinish)(fp->parent->object, fp); 808 } 809 break; 810 case PROTO_MP: 811 if (fp->proto == PROTO_LCP) { 812 struct lcp *lcp = fsm2lcp(fp); 813 814 if (lcp->want_mrru && lcp->his_mrru) { 815 log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n", 816 fp->link->name); 817 fsm_Close(fp); 818 } 819 } 820 break; 821 } 822 mbuf_Free(bp); 823} 824 825static void 826FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 827{ 828 struct lcp *lcp = fsm2lcp(fp); 829 u_char *cp; 830 u_int32_t magic; 831 832 if (lcp) { 833 cp = MBUF_CTOP(bp); 834 magic = ntohl(*(u_int32_t *)cp); 835 if (magic != lcp->his_magic) { 836 log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n", 837 fp->link->name); 838 /* XXX: We should send terminate request */ 839 } 840 if (fp->state == ST_OPENED) { 841 *(u_int32_t *)cp = htonl(lcp->want_magic); /* local magic */ 842 fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp)); 843 } 844 } 845 mbuf_Free(bp); 846} 847 848static void 849FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 850{ 851 struct lcp *lcp = fsm2lcp(fp); 852 u_int32_t magic; 853 854 if (lcp) { 855 magic = ntohl(*(u_int32_t *)MBUF_CTOP(bp)); 856 /* Tolerate echo replies with either magic number */ 857 if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) { 858 log_Printf(LogWARN, 859 "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n", 860 fp->link->name, lcp->his_magic, magic); 861 /* 862 * XXX: We should send terminate request. But poor implementations may 863 * die as a result. 864 */ 865 } 866 lqr_RecvEcho(fp, bp); 867 } 868 mbuf_Free(bp); 869} 870 871static void 872FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 873{ 874 mbuf_Free(bp); 875} 876 877static void 878FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 879{ 880 mbuf_Free(bp); 881} 882 883static void 884FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 885{ 886 mbuf_Free(bp); 887} 888 889static void 890FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 891{ 892 (*fp->fn->RecvResetReq)(fp); 893 /* 894 * All sendable compressed packets are queued in the PRI_NORMAL modem 895 * output queue.... dump 'em to the priority queue so that they arrive 896 * at the peer before our ResetAck. 897 */ 898 link_SequenceQueue(fp->link); 899 fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0); 900 mbuf_Free(bp); 901} 902 903static void 904FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 905{ 906 (*fp->fn->RecvResetAck)(fp, lhp->id); 907 mbuf_Free(bp); 908} 909 910void 911fsm_Input(struct fsm *fp, struct mbuf *bp) 912{ 913 int len; 914 struct fsmheader *lhp; 915 const struct fsmcodedesc *codep; 916 917 len = mbuf_Length(bp); 918 if (len < sizeof(struct fsmheader)) { 919 mbuf_Free(bp); 920 return; 921 } 922 lhp = (struct fsmheader *) MBUF_CTOP(bp); 923 if (lhp->code < fp->min_code || lhp->code > fp->max_code || 924 lhp->code > sizeof FsmCodes / sizeof *FsmCodes) { 925 /* 926 * Use a private id. This is really a response-type packet, but we 927 * MUST send a unique id for each REQ.... 928 */ 929 static u_char id; 930 931 fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt); 932 mbuf_Free(bp); 933 return; 934 } 935 bp->offset += sizeof(struct fsmheader); 936 bp->cnt -= sizeof(struct fsmheader); 937 938 codep = FsmCodes + lhp->code - 1; 939 if (lhp->id != fp->reqid && codep->check_reqid && 940 Enabled(fp->bundle, OPT_IDCHECK)) { 941 log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n", 942 fp->link->name, codep->name, lhp->id, fp->reqid); 943 return; 944 } 945 946 log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n", 947 fp->link->name, codep->name, lhp->id, State2Nam(fp->state)); 948 949 if (log_IsKept(LogDEBUG)) 950 mbuf_Log(); 951 952 if (codep->inc_reqid && (lhp->id == fp->reqid || 953 (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid))) 954 fp->reqid++; /* That's the end of that ``exchange''.... */ 955 956 (*codep->recv)(fp, lhp, bp); 957 958 if (log_IsKept(LogDEBUG)) 959 mbuf_Log(); 960} 961 962void 963fsm_NullRecvResetReq(struct fsm *fp) 964{ 965 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n", 966 fp->link->name); 967} 968 969void 970fsm_NullRecvResetAck(struct fsm *fp, u_char id) 971{ 972 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n", 973 fp->link->name); 974} 975 976void 977fsm_Reopen(struct fsm *fp) 978{ 979 if (fp->state == ST_OPENED) { 980 (*fp->fn->LayerDown)(fp); 981 FsmInitRestartCounter(fp); 982 FsmSendConfigReq(fp); 983 NewState(fp, ST_REQSENT); 984 (*fp->parent->LayerDown)(fp->parent->object, fp); 985 } 986} 987 988void 989fsm2initial(struct fsm *fp) 990{ 991 if (fp->state == ST_STOPPED) 992 fsm_Close(fp); 993 if (fp->state > ST_INITIAL) 994 fsm_Down(fp); 995 if (fp->state > ST_INITIAL) 996 fsm_Close(fp); 997} 998