1 /* 2 * PPP Finite State Machine for LCP/IPCP 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan, Inc. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $Id:$ 21 * 22 * TODO: 23 * o Refer loglevel for log output 24 * o Better option log display 25 */ 26 #include "fsm.h" 27 #include "hdlc.h" 28 #include "lqr.h" 29 #include "lcpproto.h" 30 #include "lcp.h" 31 32 void FsmSendConfigReq(struct fsm *fp); 33 void FsmSendTerminateReq(struct fsm *fp); 34 void FsmInitRestartCounter(struct fsm *fp); 35 void FsmTimeout(struct fsm *fp); 36 37 char *StateNames[] = { 38 "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 39 "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opend", 40 }; 41 42 void 43 FsmInit(fp) 44 struct fsm *fp; 45 { 46 #ifdef DEBUG 47 logprintf("FsmInit\n"); 48 #endif 49 fp->state = ST_INITIAL; 50 fp->reqid = 1; 51 fp->restart = 1; 52 fp->maxconfig = 3; 53 } 54 55 void 56 NewState(fp, new) 57 struct fsm *fp; 58 int new; 59 { 60 LogPrintf(LOG_LCP, "%s: state change %s --> %s\n", 61 fp->name, StateNames[fp->state], StateNames[new]); 62 fp->state = new; 63 if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) 64 StopTimer(&fp->FsmTimer); 65 } 66 67 void 68 FsmOutput(fp, code, id, ptr, count) 69 struct fsm *fp; 70 u_int code, id; 71 u_char *ptr; 72 int count; 73 { 74 int plen; 75 struct fsmheader lh; 76 struct mbuf *bp; 77 78 plen = sizeof(struct fsmheader) + count; 79 lh.code = code; 80 lh.id = id; 81 lh.length = htons(plen); 82 bp = mballoc(plen, MB_FSM); 83 bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader)); 84 if (count) 85 bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count); 86 #ifdef DEBUG 87 DumpBp(bp); 88 #endif 89 HdlcOutput(PRI_NORMAL, fp->proto, bp); 90 } 91 92 void 93 FsmOpen(fp) 94 struct fsm *fp; 95 { 96 switch (fp->state) { 97 case ST_INITIAL: 98 (fp->LayerStart)(fp); 99 NewState(fp, ST_STARTING); 100 break; 101 case ST_STARTING: 102 break; 103 case ST_CLOSED: 104 if (fp->open_mode == OPEN_PASSIVE) { 105 NewState(fp, ST_STOPPED); 106 } else { 107 FsmInitRestartCounter(fp); 108 FsmSendConfigReq(fp); 109 NewState(fp, ST_REQSENT); 110 } 111 break; 112 case ST_STOPPED: /* XXX: restart option */ 113 case ST_REQSENT: 114 case ST_ACKRCVD: 115 case ST_ACKSENT: 116 case ST_OPENED: /* XXX: restart option */ 117 break; 118 case ST_CLOSING: /* XXX: restart option */ 119 case ST_STOPPING: /* XXX: restart option */ 120 NewState(fp, ST_STOPPING); 121 break; 122 } 123 } 124 125 void 126 FsmUp(fp) 127 struct fsm *fp; 128 { 129 switch (fp->state) { 130 case ST_INITIAL: 131 NewState(fp, ST_CLOSED); 132 break; 133 case ST_STARTING: 134 FsmInitRestartCounter(fp); 135 FsmSendConfigReq(fp); 136 NewState(fp, ST_REQSENT); 137 break; 138 default: 139 LogPrintf(LOG_LCP, "%s: Oops, Up at %s\n", 140 fp->name, StateNames[fp->state]); 141 break; 142 } 143 } 144 145 void 146 FsmDown(fp) 147 struct fsm *fp; 148 { 149 switch (fp->state) { 150 case ST_CLOSED: 151 case ST_CLOSING: 152 NewState(fp, ST_INITIAL); 153 break; 154 case ST_STOPPED: 155 (fp->LayerStart)(fp); 156 /* Fall into.. */ 157 case ST_STOPPING: 158 case ST_REQSENT: 159 case ST_ACKRCVD: 160 case ST_ACKSENT: 161 NewState(fp, ST_STARTING); 162 break; 163 case ST_OPENED: 164 (fp->LayerDown)(fp); 165 NewState(fp, ST_STARTING); 166 break; 167 } 168 } 169 170 void 171 FsmClose(fp) 172 struct fsm *fp; 173 { 174 switch (fp->state) { 175 case ST_STARTING: 176 NewState(fp, ST_INITIAL); 177 break; 178 case ST_STOPPED: 179 NewState(fp, ST_CLOSED); 180 break; 181 case ST_STOPPING: 182 NewState(fp, ST_CLOSING); 183 break; 184 case ST_OPENED: 185 (fp->LayerDown)(fp); 186 /* Fall down */ 187 case ST_REQSENT: 188 case ST_ACKRCVD: 189 case ST_ACKSENT: 190 FsmInitRestartCounter(fp); 191 FsmSendTerminateReq(fp); 192 NewState(fp, ST_CLOSING); 193 break; 194 } 195 } 196 197 /* 198 * Send functions 199 */ 200 void 201 FsmSendConfigReq(fp) 202 struct fsm *fp; 203 { 204 if (--fp->maxconfig > 0) { 205 (fp->SendConfigReq)(fp); 206 StartTimer(&fp->FsmTimer); /* Start restart timer */ 207 fp->restart--; /* Decrement restart counter */ 208 } else { 209 FsmClose(fp); 210 } 211 } 212 213 void 214 FsmSendTerminateReq(fp) 215 struct fsm *fp; 216 { 217 LogPrintf(LOG_LCP, "%s: SendTerminateReq.\n", fp->name); 218 FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0); 219 (fp->SendTerminateReq)(fp); 220 StartTimer(&fp->FsmTimer); /* Start restart timer */ 221 fp->restart--; /* Decrement restart counter */ 222 } 223 224 static void 225 FsmSendConfigAck(fp, lhp, option, count) 226 struct fsm *fp; 227 struct fsmheader *lhp; 228 u_char *option; 229 int count; 230 { 231 LogPrintf(LOG_LCP, "%s: SendConfigAck(%s)\n", fp->name, StateNames[fp->state]); 232 FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count); 233 } 234 235 static void 236 FsmSendConfigRej(fp, lhp, option, count) 237 struct fsm *fp; 238 struct fsmheader *lhp; 239 u_char *option; 240 int count; 241 { 242 LogPrintf(LOG_LCP, "%s: SendConfigRej(%s)\n", fp->name, StateNames[fp->state]); 243 FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count); 244 } 245 246 static void 247 FsmSendConfigNak(fp, lhp, option, count) 248 struct fsm *fp; 249 struct fsmheader *lhp; 250 u_char *option; 251 int count; 252 { 253 LogPrintf(LOG_LCP, "%s: SendConfigNak(%s)\n", 254 fp->name, StateNames[fp->state]); 255 FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count); 256 } 257 258 /* 259 * Timeout actions 260 */ 261 void 262 FsmTimeout(fp) 263 struct fsm *fp; 264 { 265 if (fp->restart) { 266 switch (fp->state) { 267 case ST_CLOSING: 268 case ST_STOPPING: 269 FsmSendTerminateReq(fp); 270 break; 271 case ST_REQSENT: 272 case ST_ACKSENT: 273 FsmSendConfigReq(fp); 274 break; 275 case ST_ACKRCVD: 276 FsmSendConfigReq(fp); 277 NewState(fp, ST_REQSENT); 278 break; 279 } 280 StartTimer(&fp->FsmTimer); 281 } else { 282 switch (fp->state) { 283 case ST_CLOSING: 284 NewState(fp, ST_CLOSED); 285 (fp->LayerFinish)(fp); 286 break; 287 case ST_STOPPING: 288 NewState(fp, ST_STOPPED); 289 (fp->LayerFinish)(fp); 290 break; 291 case ST_REQSENT: /* XXX: 3p */ 292 case ST_ACKSENT: 293 case ST_ACKRCVD: 294 NewState(fp, ST_STOPPED); 295 (fp->LayerFinish)(fp); 296 break; 297 } 298 } 299 } 300 301 void 302 FsmInitRestartCounter(fp) 303 struct fsm *fp; 304 { 305 StopTimer(&fp->FsmTimer); 306 fp->FsmTimer.state = TIMER_STOPPED; 307 fp->FsmTimer.func = FsmTimeout; 308 fp->FsmTimer.arg = (void *)fp; 309 (fp->InitRestartCounter)(fp); 310 } 311 312 /* 313 * Actions when receive packets 314 */ 315 void 316 FsmRecvConfigReq(fp, lhp, bp) /* RCR */ 317 struct fsm *fp; 318 struct fsmheader *lhp; 319 struct mbuf *bp; 320 { 321 int plen; 322 int ackaction = 0; 323 324 plen = plength(bp); 325 if (plen < sizeof(struct fsmconfig)) { 326 logprintf("** plen = %d\n", plen); 327 pfree(bp); 328 return; 329 } 330 331 /* 332 * Check and process easy case 333 */ 334 switch (fp->state) { 335 case ST_INITIAL: 336 case ST_STARTING: 337 LogPrintf(LOG_LCP, "%s: Oops, RCR in %s.\n", 338 fp->name, StateNames[fp->state]); 339 pfree(bp); 340 return; 341 case ST_CLOSED: 342 (fp->SendTerminateAck)(fp); 343 pfree(bp); 344 return; 345 case ST_CLOSING: 346 case ST_STOPPING: 347 logprintf("## state = %d\n", fp->state); 348 pfree(bp); 349 return; 350 } 351 352 (fp->DecodeConfig)(bp, MODE_REQ); 353 354 if (nakp == NakBuff && rejp == RejBuff) 355 ackaction = 1; 356 357 switch (fp->state) { 358 case ST_OPENED: 359 (fp->LayerDown)(fp); 360 FsmSendConfigReq(fp); 361 break; 362 case ST_STOPPED: 363 FsmInitRestartCounter(fp); 364 FsmSendConfigReq(fp); 365 break; 366 } 367 368 if (rejp != RejBuff) 369 FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff); 370 if (nakp != NakBuff) 371 FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff); 372 if (ackaction) 373 FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff); 374 375 switch (fp->state) { 376 case ST_STOPPED: 377 case ST_OPENED: 378 if (ackaction) 379 NewState(fp, ST_ACKSENT); 380 else 381 NewState(fp, ST_REQSENT); 382 break; 383 case ST_REQSENT: 384 if (ackaction) 385 NewState(fp, ST_ACKSENT); 386 break; 387 case ST_ACKRCVD: 388 if (ackaction) { 389 NewState(fp, ST_OPENED); 390 (fp->LayerUp)(fp); 391 } 392 break; 393 case ST_ACKSENT: 394 if (!ackaction) 395 NewState(fp, ST_REQSENT); 396 break; 397 } 398 pfree(bp); 399 } 400 401 void 402 FsmRecvConfigAck(fp, lhp, bp) /* RCA */ 403 struct fsm *fp; 404 struct fsmheader *lhp; 405 struct mbuf *bp; 406 { 407 switch (fp->state) { 408 case ST_CLOSED: 409 case ST_STOPPED: 410 (fp->SendTerminateAck)(fp); 411 break; 412 case ST_CLOSING: 413 case ST_STOPPING: 414 break; 415 case ST_REQSENT: 416 FsmInitRestartCounter(fp); 417 NewState(fp, ST_ACKRCVD); 418 break; 419 case ST_ACKRCVD: 420 FsmSendConfigReq(fp); 421 NewState(fp, ST_REQSENT); 422 break; 423 case ST_ACKSENT: 424 FsmInitRestartCounter(fp); 425 NewState(fp, ST_OPENED); 426 (fp->LayerUp)(fp); 427 break; 428 case ST_OPENED: 429 (fp->LayerDown)(fp); 430 FsmSendConfigReq(fp); 431 NewState(fp, ST_REQSENT); 432 break; 433 } 434 pfree(bp); 435 } 436 437 void 438 FsmRecvConfigNak(fp, lhp, bp) /* RCN */ 439 struct fsm *fp; 440 struct fsmheader *lhp; 441 struct mbuf *bp; 442 { 443 int plen; 444 445 plen = plength(bp); 446 if (plen < sizeof(struct fsmconfig)) { 447 pfree(bp); 448 return; 449 } 450 451 /* 452 * Check and process easy case 453 */ 454 switch (fp->state) { 455 case ST_INITIAL: 456 case ST_STARTING: 457 LogPrintf(LOG_LCP, "%s: Oops, RCN in %s.\n", 458 fp->name, StateNames[fp->state]); 459 pfree(bp); 460 return; 461 case ST_CLOSED: 462 case ST_STOPPED: 463 (fp->SendTerminateAck)(fp); 464 pfree(bp); 465 return; 466 case ST_CLOSING: 467 case ST_STOPPING: 468 pfree(bp); 469 return; 470 } 471 472 (fp->DecodeConfig)(bp, MODE_NAK); 473 474 switch (fp->state) { 475 case ST_REQSENT: 476 case ST_ACKSENT: 477 FsmInitRestartCounter(fp); 478 FsmSendConfigReq(fp); 479 break; 480 case ST_OPENED: 481 (fp->LayerDown)(fp); 482 /* Fall down */ 483 case ST_ACKRCVD: 484 FsmSendConfigReq(fp); 485 NewState(fp, ST_REQSENT); 486 break; 487 } 488 489 pfree(bp); 490 } 491 492 void 493 FsmRecvTermReq(fp, lhp, bp) /* RTR */ 494 struct fsm *fp; 495 struct fsmheader *lhp; 496 struct mbuf *bp; 497 { 498 switch (fp->state) { 499 case ST_INITIAL: 500 case ST_STARTING: 501 LogPrintf(LOG_LCP, "%s: Oops, RTR in %s\n", fp->name, 502 StateNames[fp->state]); 503 break; 504 case ST_CLOSED: 505 case ST_STOPPED: 506 case ST_CLOSING: 507 case ST_STOPPING: 508 case ST_REQSENT: 509 (fp->SendTerminateAck)(fp); 510 break; 511 case ST_ACKRCVD: 512 case ST_ACKSENT: 513 (fp->SendTerminateAck)(fp); 514 NewState(fp, ST_REQSENT); 515 break; 516 case ST_OPENED: 517 (fp->LayerDown)(fp); 518 /* Zero Restart counter */ 519 (fp->SendTerminateAck)(fp); 520 NewState(fp, ST_STOPPING); 521 break; 522 } 523 pfree(bp); 524 } 525 526 void 527 FsmRecvTermAck(fp, lhp, bp) /* RTA */ 528 struct fsm *fp; 529 struct fsmheader *lhp; 530 struct mbuf *bp; 531 { 532 switch (fp->state) { 533 case ST_CLOSING: 534 NewState(fp, ST_CLOSED); 535 (fp->LayerFinish)(fp); 536 break; 537 case ST_STOPPING: 538 NewState(fp, ST_STOPPED); 539 (fp->LayerFinish)(fp); 540 break; 541 case ST_ACKRCVD: 542 NewState(fp, ST_REQSENT); 543 break; 544 case ST_OPENED: 545 (fp->LayerDown)(fp); 546 FsmSendConfigReq(fp); 547 NewState(fp, ST_REQSENT); 548 break; 549 } 550 pfree(bp); 551 } 552 553 void 554 FsmRecvConfigRej(fp, lhp, bp) /* RCJ */ 555 struct fsm *fp; 556 struct fsmheader *lhp; 557 struct mbuf *bp; 558 { 559 int plen; 560 561 plen = plength(bp); 562 if (plen < sizeof(struct fsmconfig)) { 563 pfree(bp); 564 return; 565 } 566 LogPrintf(LOG_LCP, "%s: RecvConfigRej.\n", fp->name); 567 568 /* 569 * Check and process easy case 570 */ 571 switch (fp->state) { 572 case ST_INITIAL: 573 case ST_STARTING: 574 LogPrintf(LOG_LCP, "%s: Oops, RCJ in %s.\n", 575 fp->name, StateNames[fp->state]); 576 pfree(bp); 577 return; 578 case ST_CLOSED: 579 case ST_STOPPED: 580 (fp->SendTerminateAck)(fp); 581 pfree(bp); 582 return; 583 case ST_CLOSING: 584 case ST_STOPPING: 585 pfree(bp); 586 return; 587 } 588 589 (fp->DecodeConfig)(bp, MODE_REJ); 590 591 switch (fp->state) { 592 case ST_REQSENT: 593 case ST_ACKSENT: 594 FsmInitRestartCounter(fp); 595 FsmSendConfigReq(fp); 596 break; 597 case ST_OPENED: 598 (fp->LayerDown)(fp); 599 /* Fall down */ 600 case ST_ACKRCVD: 601 FsmSendConfigReq(fp); 602 NewState(fp, ST_REQSENT); 603 break; 604 } 605 pfree(bp); 606 } 607 608 void 609 FsmRecvCodeRej(fp, lhp, bp) 610 struct fsm *fp; 611 struct fsmheader *lhp; 612 struct mbuf *bp; 613 { 614 LogPrintf(LOG_LCP, "%s: RecvCodeRej\n", fp->name); 615 pfree(bp); 616 } 617 618 void 619 FsmRecvProtoRej(fp, lhp, bp) 620 struct fsm *fp; 621 struct fsmheader *lhp; 622 struct mbuf *bp; 623 { 624 u_short *sp, proto; 625 626 sp = (u_short *)MBUF_CTOP(bp); 627 proto = ntohs(*sp); 628 LogPrintf(LOG_LCP, "-- Protocol (%04x) was rejected.\n", proto); 629 630 switch (proto) { 631 case PROTO_LQR: 632 StopLqr(LQM_LQR); 633 break; 634 case PROTO_CCP: 635 fp = &CcpFsm; 636 (fp->LayerFinish)(fp); 637 switch (fp->state) { 638 case ST_CLOSED: 639 case ST_CLOSING: 640 NewState(fp, ST_CLOSED); 641 default: 642 NewState(fp, ST_STOPPED); 643 break; 644 } 645 break; 646 } 647 pfree(bp); 648 } 649 650 void 651 FsmRecvEchoReq(fp, lhp, bp) 652 struct fsm *fp; 653 struct fsmheader *lhp; 654 struct mbuf *bp; 655 { 656 u_char *cp; 657 u_long *lp, magic; 658 659 cp = MBUF_CTOP(bp); 660 lp = (u_long *)cp; 661 magic = ntohl(*lp); 662 if (magic != LcpInfo.his_magic) { 663 logprintf("RecvEchoReq: his magic is bad!!\n"); 664 /* XXX: We should send terminate request */ 665 } 666 667 if (fp->state == ST_OPENED) { 668 *lp = htonl(LcpInfo.want_magic); /* Insert local magic number */ 669 LogPrintf(LOG_LCP, "%s: SendEchoRep(%s)\n", fp->name, StateNames[fp->state]); 670 FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp)); 671 } 672 pfree(bp); 673 } 674 675 void 676 FsmRecvEchoRep(fp, lhp, bp) 677 struct fsm *fp; 678 struct fsmheader *lhp; 679 struct mbuf *bp; 680 { 681 u_long *lp, magic; 682 683 lp = (u_long *)MBUF_CTOP(bp); 684 magic = ntohl(*lp); 685 if (magic != 0 && magic != LcpInfo.his_magic) { 686 logprintf("RecvEchoRep: his magic is wrong! expect: %x got: %x\n", 687 LcpInfo.his_magic, magic); 688 /* 689 * XXX: We should send terminate request. But poor implementation 690 * may die as a result. 691 */ 692 } 693 RecvEchoLqr(bp); 694 pfree(bp); 695 } 696 697 void 698 FsmRecvDiscReq(fp, lhp, bp) 699 struct fsm *fp; 700 struct fsmheader *lhp; 701 struct mbuf *bp; 702 { 703 LogPrintf(LOG_LCP, "%s: RecvDiscReq\n", fp->name); 704 pfree(bp); 705 } 706 707 void 708 FsmRecvIdent(fp, lhp, bp) 709 struct fsm *fp; 710 struct fsmheader *lhp; 711 struct mbuf *bp; 712 { 713 LogPrintf(LOG_LCP, "%s: RecvIdent\n", fp->name); 714 pfree(bp); 715 } 716 717 void 718 FsmRecvTimeRemain(fp, lhp, bp) 719 struct fsm *fp; 720 struct fsmheader *lhp; 721 struct mbuf *bp; 722 { 723 LogPrintf(LOG_LCP, "%s: RecvTimeRemain\n", fp->name); 724 pfree(bp); 725 } 726 727 void 728 FsmRecvResetReq(fp, lhp, bp) 729 struct fsm *fp; 730 struct fsmheader *lhp; 731 struct mbuf *bp; 732 { 733 LogPrintf(LOG_LCP, "%s: RecvResetReq\n", fp->name); 734 CcpRecvResetReq(fp); 735 LogPrintf(LOG_LCP, "%s: SendResetAck\n", fp->name); 736 FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0); 737 pfree(bp); 738 } 739 740 void 741 FsmRecvResetAck(fp, lhp, bp) 742 struct fsm *fp; 743 struct fsmheader *lhp; 744 struct mbuf *bp; 745 { 746 LogPrintf(LOG_LCP, "%s: RecvResetAck\n", fp->name); 747 fp->reqid++; 748 pfree(bp); 749 } 750 751 struct fsmcodedesc FsmCodes[] = { 752 { FsmRecvConfigReq, "Configure Request", }, 753 { FsmRecvConfigAck, "Configure Ack", }, 754 { FsmRecvConfigNak, "Configure Nak", }, 755 { FsmRecvConfigRej, "Configure Reject", }, 756 { FsmRecvTermReq, "Terminate Request", }, 757 { FsmRecvTermAck, "Terminate Ack", }, 758 { FsmRecvCodeRej, "Code Reject", }, 759 { FsmRecvProtoRej, "Protocol Reject", }, 760 { FsmRecvEchoReq, "Echo Request", }, 761 { FsmRecvEchoRep, "Echo Reply", }, 762 { FsmRecvDiscReq, "Discard Request", }, 763 { FsmRecvIdent, "Ident", }, 764 { FsmRecvTimeRemain, "Time Remain", }, 765 { FsmRecvResetReq, "Reset Request", }, 766 { FsmRecvResetAck, "Reset Ack", }, 767 }; 768 769 void 770 FsmInput(fp, bp) 771 struct fsm *fp; 772 struct mbuf *bp; 773 { 774 int len; 775 struct fsmheader *lhp; 776 struct fsmcodedesc *codep; 777 778 len = plength(bp); 779 if (len < sizeof(struct fsmheader)) { 780 pfree(bp); 781 return; 782 } 783 lhp = (struct fsmheader *)MBUF_CTOP(bp); 784 if (lhp->code == 0 || lhp->code > fp->max_code) { 785 pfree(bp); /* XXX: Should send code reject */ 786 return; 787 } 788 789 bp->offset += sizeof(struct fsmheader); 790 bp->cnt -= sizeof(struct fsmheader); 791 792 codep = FsmCodes + lhp->code - 1; 793 LogPrintf(LOG_LCP, "%s: Received %s (%d) state = %s (%d)\n", 794 fp->name, codep->name, lhp->code, StateNames[fp->state], fp->state); 795 #ifdef DEBUG 796 LogMemory(); 797 #endif 798 (codep->action)(fp, lhp, bp); 799 #ifdef DEBUG 800 LogMemory(); 801 #endif 802 } 803