fsm.c revision 37160
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: fsm.c,v 1.32 1998/06/20 01:55:28 brian Exp $ 21 * 22 * TODO: 23 */ 24 25#include <sys/types.h> 26#include <netinet/in.h> 27#include <netinet/in_systm.h> 28#include <netinet/ip.h> 29#include <sys/un.h> 30 31#include <string.h> 32#include <termios.h> 33 34#include "mbuf.h" 35#include "log.h" 36#include "defs.h" 37#include "timer.h" 38#include "fsm.h" 39#include "iplist.h" 40#include "lqr.h" 41#include "hdlc.h" 42#include "throughput.h" 43#include "slcompress.h" 44#include "ipcp.h" 45#include "filter.h" 46#include "descriptor.h" 47#include "lcp.h" 48#include "ccp.h" 49#include "link.h" 50#include "mp.h" 51#include "bundle.h" 52#include "async.h" 53#include "physical.h" 54#include "lcpproto.h" 55 56static void FsmSendConfigReq(struct fsm *); 57static void FsmSendTerminateReq(struct fsm *); 58static void FsmInitRestartCounter(struct fsm *); 59 60typedef void (recvfn)(struct fsm *, struct fsmheader *, struct mbuf *); 61static recvfn FsmRecvConfigReq, FsmRecvConfigAck, FsmRecvConfigNak, 62 FsmRecvConfigRej, FsmRecvTermReq, FsmRecvTermAck, 63 FsmRecvCodeRej, FsmRecvProtoRej, FsmRecvEchoReq, 64 FsmRecvEchoRep, FsmRecvDiscReq, FsmRecvIdent, 65 FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck; 66 67static const struct fsmcodedesc { 68 recvfn *recv; 69 unsigned check_reqid : 1; 70 unsigned inc_reqid : 1; 71 const char *name; 72} FsmCodes[] = { 73 { FsmRecvConfigReq, 0, 0, "ConfigReq" }, 74 { FsmRecvConfigAck, 1, 1, "ConfigAck" }, 75 { FsmRecvConfigNak, 1, 1, "ConfigNak" }, 76 { FsmRecvConfigRej, 1, 1, "ConfigRej" }, 77 { FsmRecvTermReq, 0, 0, "TerminateReq" }, 78 { FsmRecvTermAck, 1, 1, "TerminateAck" }, 79 { FsmRecvCodeRej, 0, 0, "CodeRej" }, 80 { FsmRecvProtoRej, 0, 0, "ProtocolRej" }, 81 { FsmRecvEchoReq, 0, 0, "EchoRequest" }, 82 { FsmRecvEchoRep, 0, 0, "EchoReply" }, 83 { FsmRecvDiscReq, 0, 0, "DiscardReq" }, 84 { FsmRecvIdent, 0, 0, "Ident" }, 85 { FsmRecvTimeRemain,0, 0, "TimeRemain" }, 86 { FsmRecvResetReq, 0, 0, "ResetReqt" }, 87 { FsmRecvResetAck, 0, 1, "ResetAck" } 88}; 89 90static const char * 91Code2Nam(u_int code) 92{ 93 if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0]) 94 return "Unknown"; 95 return FsmCodes[code-1].name; 96} 97 98const char * 99State2Nam(u_int state) 100{ 101 static const char *StateNames[] = { 102 "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 103 "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened", 104 }; 105 106 if (state >= sizeof StateNames / sizeof StateNames[0]) 107 return "unknown"; 108 return StateNames[state]; 109} 110 111static void 112StoppedTimeout(void *v) 113{ 114 struct fsm *fp = (struct fsm *)v; 115 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 FsmInitRestartCounter(fp); 214 FsmSendConfigReq(fp); 215 NewState(fp, ST_REQSENT); 216 } 217} 218 219void 220fsm_Open(struct fsm * fp) 221{ 222 switch (fp->state) { 223 case ST_INITIAL: 224 NewState(fp, ST_STARTING); 225 (*fp->fn->LayerStart)(fp); 226 (*fp->parent->LayerStart)(fp->parent->object, fp); 227 break; 228 case ST_CLOSED: 229 if (fp->open_mode == OPEN_PASSIVE) { 230 NewState(fp, ST_STOPPED); 231 } else if (fp->open_mode > 0) { 232 if (fp->open_mode > 1) 233 log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n", 234 fp->link->name, fp->open_mode); 235 NewState(fp, ST_STOPPED); 236 timer_Stop(&fp->OpenTimer); 237 fp->OpenTimer.load = fp->open_mode * SECTICKS; 238 fp->OpenTimer.func = FsmOpenNow; 239 fp->OpenTimer.arg = (void *)fp; 240 timer_Start(&fp->OpenTimer); 241 } else 242 FsmOpenNow(fp); 243 break; 244 case ST_STOPPED: /* XXX: restart option */ 245 case ST_REQSENT: 246 case ST_ACKRCVD: 247 case ST_ACKSENT: 248 case ST_OPENED: /* XXX: restart option */ 249 break; 250 case ST_CLOSING: /* XXX: restart option */ 251 case ST_STOPPING: /* XXX: restart option */ 252 NewState(fp, ST_STOPPING); 253 break; 254 } 255} 256 257void 258fsm_Up(struct fsm * fp) 259{ 260 switch (fp->state) { 261 case ST_INITIAL: 262 log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n", 263 fp->link->name); 264 NewState(fp, ST_CLOSED); 265 break; 266 case ST_STARTING: 267 FsmInitRestartCounter(fp); 268 FsmSendConfigReq(fp); 269 NewState(fp, ST_REQSENT); 270 break; 271 default: 272 log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n", 273 fp->link->name, State2Nam(fp->state)); 274 break; 275 } 276} 277 278void 279fsm_Down(struct fsm *fp) 280{ 281 switch (fp->state) { 282 case ST_CLOSED: 283 NewState(fp, ST_INITIAL); 284 break; 285 case ST_CLOSING: 286 (*fp->fn->LayerFinish)(fp); 287 NewState(fp, ST_INITIAL); 288 (*fp->parent->LayerFinish)(fp->parent->object, fp); 289 break; 290 case ST_STOPPED: 291 NewState(fp, ST_STARTING); 292 (*fp->fn->LayerStart)(fp); 293 (*fp->parent->LayerStart)(fp->parent->object, fp); 294 break; 295 case ST_STOPPING: 296 case ST_REQSENT: 297 case ST_ACKRCVD: 298 case ST_ACKSENT: 299 NewState(fp, ST_STARTING); 300 break; 301 case ST_OPENED: 302 (*fp->fn->LayerDown)(fp); 303 NewState(fp, ST_STARTING); 304 (*fp->parent->LayerDown)(fp->parent->object, fp); 305 break; 306 } 307} 308 309void 310fsm_Close(struct fsm *fp) 311{ 312 switch (fp->state) { 313 case ST_STARTING: 314 (*fp->fn->LayerFinish)(fp); 315 NewState(fp, ST_INITIAL); 316 (*fp->parent->LayerFinish)(fp->parent->object, fp); 317 break; 318 case ST_STOPPED: 319 NewState(fp, ST_CLOSED); 320 break; 321 case ST_STOPPING: 322 NewState(fp, ST_CLOSING); 323 break; 324 case ST_OPENED: 325 (*fp->fn->LayerDown)(fp); 326 FsmInitRestartCounter(fp); 327 FsmSendTerminateReq(fp); 328 NewState(fp, ST_CLOSING); 329 (*fp->parent->LayerDown)(fp->parent->object, fp); 330 break; 331 case ST_REQSENT: 332 case ST_ACKRCVD: 333 case ST_ACKSENT: 334 FsmInitRestartCounter(fp); 335 FsmSendTerminateReq(fp); 336 NewState(fp, ST_CLOSING); 337 break; 338 } 339} 340 341/* 342 * Send functions 343 */ 344static void 345FsmSendConfigReq(struct fsm * fp) 346{ 347 if (--fp->maxconfig > 0) { 348 (*fp->fn->SendConfigReq)(fp); 349 timer_Start(&fp->FsmTimer); /* Start restart timer */ 350 fp->restart--; /* Decrement restart counter */ 351 } else { 352 fsm_Close(fp); 353 } 354} 355 356static void 357FsmSendTerminateReq(struct fsm *fp) 358{ 359 fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0); 360 (*fp->fn->SentTerminateReq)(fp); 361 timer_Start(&fp->FsmTimer); /* Start restart timer */ 362 fp->restart--; /* Decrement restart counter */ 363} 364 365/* 366 * Timeout actions 367 */ 368static void 369FsmTimeout(void *v) 370{ 371 struct fsm *fp = (struct fsm *)v; 372 373 if (fp->restart) { 374 switch (fp->state) { 375 case ST_CLOSING: 376 case ST_STOPPING: 377 FsmSendTerminateReq(fp); 378 break; 379 case ST_REQSENT: 380 case ST_ACKSENT: 381 FsmSendConfigReq(fp); 382 break; 383 case ST_ACKRCVD: 384 FsmSendConfigReq(fp); 385 NewState(fp, ST_REQSENT); 386 break; 387 } 388 timer_Start(&fp->FsmTimer); 389 } else { 390 switch (fp->state) { 391 case ST_CLOSING: 392 (*fp->fn->LayerFinish)(fp); 393 NewState(fp, ST_CLOSED); 394 (*fp->parent->LayerFinish)(fp->parent->object, fp); 395 break; 396 case ST_STOPPING: 397 (*fp->fn->LayerFinish)(fp); 398 NewState(fp, ST_STOPPED); 399 (*fp->parent->LayerFinish)(fp->parent->object, fp); 400 break; 401 case ST_REQSENT: /* XXX: 3p */ 402 case ST_ACKSENT: 403 case ST_ACKRCVD: 404 (*fp->fn->LayerFinish)(fp); 405 NewState(fp, ST_STOPPED); 406 (*fp->parent->LayerFinish)(fp->parent->object, fp); 407 break; 408 } 409 } 410} 411 412static void 413FsmInitRestartCounter(struct fsm * fp) 414{ 415 timer_Stop(&fp->FsmTimer); 416 fp->FsmTimer.func = FsmTimeout; 417 fp->FsmTimer.arg = (void *) fp; 418 (*fp->fn->InitRestartCounter)(fp); 419} 420 421/* 422 * Actions when receive packets 423 */ 424static void 425FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 426/* RCR */ 427{ 428 struct fsm_decode dec; 429 int plen, flen; 430 int ackaction = 0; 431 432 plen = mbuf_Length(bp); 433 flen = ntohs(lhp->length) - sizeof *lhp; 434 if (plen < flen) { 435 log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n", 436 fp->link->name, plen, flen); 437 mbuf_Free(bp); 438 return; 439 } 440 441 /* 442 * Check and process easy case 443 */ 444 switch (fp->state) { 445 case ST_INITIAL: 446 case ST_STARTING: 447 log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n", 448 fp->link->name, State2Nam(fp->state)); 449 mbuf_Free(bp); 450 return; 451 case ST_CLOSED: 452 (*fp->fn->SendTerminateAck)(fp, lhp->id); 453 mbuf_Free(bp); 454 return; 455 case ST_CLOSING: 456 log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n", 457 fp->link->name, State2Nam(fp->state)); 458 case ST_STOPPING: 459 mbuf_Free(bp); 460 return; 461 } 462 463 dec.ackend = dec.ack; 464 dec.nakend = dec.nak; 465 dec.rejend = dec.rej; 466 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec); 467 if (flen < sizeof(struct fsmconfig)) 468 log_Printf(fp->LogLevel, " [EMPTY]\n"); 469 470 if (dec.nakend == dec.nak && dec.rejend == dec.rej) 471 ackaction = 1; 472 473 switch (fp->state) { 474 case ST_OPENED: 475 (*fp->fn->LayerDown)(fp); 476 FsmSendConfigReq(fp); 477 (*fp->parent->LayerDown)(fp->parent->object, fp); 478 break; 479 case ST_STOPPED: 480 FsmInitRestartCounter(fp); 481 FsmSendConfigReq(fp); 482 break; 483 } 484 485 if (dec.rejend != dec.rej) 486 fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej); 487 if (dec.nakend != dec.nak) 488 fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak); 489 if (ackaction) 490 fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack); 491 492 switch (fp->state) { 493 case ST_OPENED: 494 case ST_STOPPED: 495 if (ackaction) 496 NewState(fp, ST_ACKSENT); 497 else 498 NewState(fp, ST_REQSENT); 499 break; 500 case ST_REQSENT: 501 if (ackaction) 502 NewState(fp, ST_ACKSENT); 503 break; 504 case ST_ACKRCVD: 505 if (ackaction) { 506 NewState(fp, ST_OPENED); 507 if ((*fp->fn->LayerUp)(fp)) 508 (*fp->parent->LayerUp)(fp->parent->object, fp); 509 else { 510 (*fp->fn->LayerDown)(fp); 511 FsmInitRestartCounter(fp); 512 FsmSendTerminateReq(fp); 513 NewState(fp, ST_CLOSING); 514 } 515 } 516 break; 517 case ST_ACKSENT: 518 if (!ackaction) 519 NewState(fp, ST_REQSENT); 520 break; 521 } 522 mbuf_Free(bp); 523} 524 525static void 526FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 527/* RCA */ 528{ 529 switch (fp->state) { 530 case ST_CLOSED: 531 case ST_STOPPED: 532 (*fp->fn->SendTerminateAck)(fp, lhp->id); 533 break; 534 case ST_CLOSING: 535 case ST_STOPPING: 536 break; 537 case ST_REQSENT: 538 FsmInitRestartCounter(fp); 539 NewState(fp, ST_ACKRCVD); 540 break; 541 case ST_ACKRCVD: 542 FsmSendConfigReq(fp); 543 NewState(fp, ST_REQSENT); 544 break; 545 case ST_ACKSENT: 546 FsmInitRestartCounter(fp); 547 NewState(fp, ST_OPENED); 548 if ((*fp->fn->LayerUp)(fp)) 549 (*fp->parent->LayerUp)(fp->parent->object, fp); 550 else { 551 (*fp->fn->LayerDown)(fp); 552 FsmInitRestartCounter(fp); 553 FsmSendTerminateReq(fp); 554 NewState(fp, ST_CLOSING); 555 } 556 break; 557 case ST_OPENED: 558 (*fp->fn->LayerDown)(fp); 559 FsmSendConfigReq(fp); 560 NewState(fp, ST_REQSENT); 561 (*fp->parent->LayerDown)(fp->parent->object, fp); 562 break; 563 } 564 mbuf_Free(bp); 565} 566 567static void 568FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 569/* RCN */ 570{ 571 struct fsm_decode dec; 572 int plen, flen; 573 574 plen = mbuf_Length(bp); 575 flen = ntohs(lhp->length) - sizeof *lhp; 576 if (plen < flen) { 577 mbuf_Free(bp); 578 return; 579 } 580 581 /* 582 * Check and process easy case 583 */ 584 switch (fp->state) { 585 case ST_INITIAL: 586 case ST_STARTING: 587 log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n", 588 fp->link->name, State2Nam(fp->state)); 589 mbuf_Free(bp); 590 return; 591 case ST_CLOSED: 592 case ST_STOPPED: 593 (*fp->fn->SendTerminateAck)(fp, lhp->id); 594 mbuf_Free(bp); 595 return; 596 case ST_CLOSING: 597 case ST_STOPPING: 598 mbuf_Free(bp); 599 return; 600 } 601 602 dec.ackend = dec.ack; 603 dec.nakend = dec.nak; 604 dec.rejend = dec.rej; 605 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec); 606 if (flen < sizeof(struct fsmconfig)) 607 log_Printf(fp->LogLevel, " [EMPTY]\n"); 608 609 switch (fp->state) { 610 case ST_REQSENT: 611 case ST_ACKSENT: 612 FsmInitRestartCounter(fp); 613 FsmSendConfigReq(fp); 614 break; 615 case ST_OPENED: 616 (*fp->fn->LayerDown)(fp); 617 FsmSendConfigReq(fp); 618 NewState(fp, ST_REQSENT); 619 (*fp->parent->LayerDown)(fp->parent->object, fp); 620 break; 621 case ST_ACKRCVD: 622 FsmSendConfigReq(fp); 623 NewState(fp, ST_REQSENT); 624 break; 625 } 626 627 mbuf_Free(bp); 628} 629 630static void 631FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 632/* RTR */ 633{ 634 switch (fp->state) { 635 case ST_INITIAL: 636 case ST_STARTING: 637 log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n", 638 fp->link->name, State2Nam(fp->state)); 639 break; 640 case ST_CLOSED: 641 case ST_STOPPED: 642 case ST_CLOSING: 643 case ST_STOPPING: 644 case ST_REQSENT: 645 (*fp->fn->SendTerminateAck)(fp, lhp->id); 646 break; 647 case ST_ACKRCVD: 648 case ST_ACKSENT: 649 (*fp->fn->SendTerminateAck)(fp, lhp->id); 650 NewState(fp, ST_REQSENT); 651 break; 652 case ST_OPENED: 653 (*fp->fn->LayerDown)(fp); 654 (*fp->fn->SendTerminateAck)(fp, lhp->id); 655 FsmInitRestartCounter(fp); 656 timer_Start(&fp->FsmTimer); /* Start restart timer */ 657 fp->restart = 0; 658 NewState(fp, ST_STOPPING); 659 (*fp->parent->LayerDown)(fp->parent->object, fp); 660 break; 661 } 662 mbuf_Free(bp); 663} 664 665static void 666FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 667/* RTA */ 668{ 669 switch (fp->state) { 670 case ST_CLOSING: 671 (*fp->fn->LayerFinish)(fp); 672 NewState(fp, ST_CLOSED); 673 (*fp->parent->LayerFinish)(fp->parent->object, fp); 674 break; 675 case ST_STOPPING: 676 (*fp->fn->LayerFinish)(fp); 677 NewState(fp, ST_STOPPED); 678 (*fp->parent->LayerFinish)(fp->parent->object, fp); 679 break; 680 case ST_ACKRCVD: 681 NewState(fp, ST_REQSENT); 682 break; 683 case ST_OPENED: 684 (*fp->fn->LayerDown)(fp); 685 FsmSendConfigReq(fp); 686 NewState(fp, ST_REQSENT); 687 (*fp->parent->LayerDown)(fp->parent->object, fp); 688 break; 689 } 690 mbuf_Free(bp); 691} 692 693static void 694FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 695/* RCJ */ 696{ 697 struct fsm_decode dec; 698 int plen, flen; 699 700 plen = mbuf_Length(bp); 701 flen = ntohs(lhp->length) - sizeof *lhp; 702 if (plen < flen) { 703 mbuf_Free(bp); 704 return; 705 } 706 707 /* 708 * Check and process easy case 709 */ 710 switch (fp->state) { 711 case ST_INITIAL: 712 case ST_STARTING: 713 log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n", 714 fp->link->name, State2Nam(fp->state)); 715 mbuf_Free(bp); 716 return; 717 case ST_CLOSED: 718 case ST_STOPPED: 719 (*fp->fn->SendTerminateAck)(fp, lhp->id); 720 mbuf_Free(bp); 721 return; 722 case ST_CLOSING: 723 case ST_STOPPING: 724 mbuf_Free(bp); 725 return; 726 } 727 728 dec.ackend = dec.ack; 729 dec.nakend = dec.nak; 730 dec.rejend = dec.rej; 731 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec); 732 if (flen < sizeof(struct fsmconfig)) 733 log_Printf(fp->LogLevel, " [EMPTY]\n"); 734 735 switch (fp->state) { 736 case ST_REQSENT: 737 case ST_ACKSENT: 738 FsmInitRestartCounter(fp); 739 FsmSendConfigReq(fp); 740 break; 741 case ST_OPENED: 742 (*fp->fn->LayerDown)(fp); 743 FsmSendConfigReq(fp); 744 NewState(fp, ST_REQSENT); 745 (*fp->parent->LayerDown)(fp->parent->object, fp); 746 break; 747 case ST_ACKRCVD: 748 FsmSendConfigReq(fp); 749 NewState(fp, ST_REQSENT); 750 break; 751 } 752 mbuf_Free(bp); 753} 754 755static void 756FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 757{ 758 mbuf_Free(bp); 759} 760 761static void 762FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 763{ 764 struct physical *p = link2physical(fp->link); 765 u_short *sp, proto; 766 767 sp = (u_short *) MBUF_CTOP(bp); 768 proto = ntohs(*sp); 769 log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n", 770 fp->link->name, proto, hdlc_Protocol2Nam(proto)); 771 772 switch (proto) { 773 case PROTO_LQR: 774 if (p) 775 lqr_Stop(p, LQM_LQR); 776 else 777 log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n", 778 fp->link->name); 779 break; 780 case PROTO_CCP: 781 if (fp->proto == PROTO_LCP) { 782 fp = &fp->link->ccp.fsm; 783 (*fp->fn->LayerFinish)(fp); 784 switch (fp->state) { 785 case ST_CLOSED: 786 case ST_CLOSING: 787 NewState(fp, ST_CLOSED); 788 default: 789 NewState(fp, ST_STOPPED); 790 break; 791 } 792 (*fp->parent->LayerFinish)(fp->parent->object, fp); 793 } 794 break; 795 case PROTO_MP: 796 if (fp->proto == PROTO_LCP) { 797 struct lcp *lcp = fsm2lcp(fp); 798 799 if (lcp->want_mrru && lcp->his_mrru) { 800 log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n", 801 fp->link->name); 802 fsm_Close(fp); 803 } 804 } 805 break; 806 } 807 mbuf_Free(bp); 808} 809 810static void 811FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 812{ 813 struct lcp *lcp = fsm2lcp(fp); 814 u_char *cp; 815 u_int32_t magic; 816 817 if (lcp) { 818 cp = MBUF_CTOP(bp); 819 magic = ntohl(*(u_int32_t *)cp); 820 if (magic != lcp->his_magic) { 821 log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n", 822 fp->link->name); 823 /* XXX: We should send terminate request */ 824 } 825 if (fp->state == ST_OPENED) { 826 *(u_int32_t *)cp = htonl(lcp->want_magic); /* local magic */ 827 fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp)); 828 } 829 } 830 mbuf_Free(bp); 831} 832 833static void 834FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 835{ 836 struct lcp *lcp = fsm2lcp(fp); 837 u_int32_t magic; 838 839 if (lcp) { 840 magic = ntohl(*(u_int32_t *)MBUF_CTOP(bp)); 841 /* Tolerate echo replies with either magic number */ 842 if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) { 843 log_Printf(LogWARN, 844 "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n", 845 fp->link->name, lcp->his_magic, magic); 846 /* 847 * XXX: We should send terminate request. But poor implementations may 848 * die as a result. 849 */ 850 } 851 lqr_RecvEcho(fp, bp); 852 } 853 mbuf_Free(bp); 854} 855 856static void 857FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 858{ 859 mbuf_Free(bp); 860} 861 862static void 863FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 864{ 865 mbuf_Free(bp); 866} 867 868static void 869FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 870{ 871 mbuf_Free(bp); 872} 873 874static void 875FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 876{ 877 (*fp->fn->RecvResetReq)(fp); 878 /* 879 * All sendable compressed packets are queued in the PRI_NORMAL modem 880 * output queue.... dump 'em to the priority queue so that they arrive 881 * at the peer before our ResetAck. 882 */ 883 link_SequenceQueue(fp->link); 884 fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0); 885 mbuf_Free(bp); 886} 887 888static void 889FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 890{ 891 (*fp->fn->RecvResetAck)(fp, lhp->id); 892 mbuf_Free(bp); 893} 894 895void 896fsm_Input(struct fsm *fp, struct mbuf *bp) 897{ 898 int len; 899 struct fsmheader *lhp; 900 const struct fsmcodedesc *codep; 901 902 len = mbuf_Length(bp); 903 if (len < sizeof(struct fsmheader)) { 904 mbuf_Free(bp); 905 return; 906 } 907 lhp = (struct fsmheader *) MBUF_CTOP(bp); 908 if (lhp->code < fp->min_code || lhp->code > fp->max_code || 909 lhp->code > sizeof FsmCodes / sizeof *FsmCodes) { 910 /* 911 * Use a private id. This is really a response-type packet, but we 912 * MUST send a unique id for each REQ.... 913 */ 914 static u_char id; 915 916 fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt); 917 mbuf_Free(bp); 918 return; 919 } 920 bp->offset += sizeof(struct fsmheader); 921 bp->cnt -= sizeof(struct fsmheader); 922 923 codep = FsmCodes + lhp->code - 1; 924 if (lhp->id != fp->reqid && codep->check_reqid && 925 Enabled(fp->bundle, OPT_IDCHECK)) { 926 log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n", 927 fp->link->name, codep->name, lhp->id, fp->reqid); 928 return; 929 } 930 931 log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n", 932 fp->link->name, codep->name, lhp->id, State2Nam(fp->state)); 933 934 if (log_IsKept(LogDEBUG)) 935 mbuf_Log(); 936 937 if (codep->inc_reqid && (lhp->id == fp->reqid || 938 (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid))) 939 fp->reqid++; /* That's the end of that ``exchange''.... */ 940 941 (*codep->recv)(fp, lhp, bp); 942 943 if (log_IsKept(LogDEBUG)) 944 mbuf_Log(); 945} 946 947void 948fsm_NullRecvResetReq(struct fsm *fp) 949{ 950 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n", 951 fp->link->name); 952} 953 954void 955fsm_NullRecvResetAck(struct fsm *fp, u_char id) 956{ 957 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n", 958 fp->link->name); 959} 960 961void 962fsm_Reopen(struct fsm *fp) 963{ 964 if (fp->state == ST_OPENED) { 965 (*fp->fn->LayerDown)(fp); 966 FsmInitRestartCounter(fp); 967 FsmSendConfigReq(fp); 968 NewState(fp, ST_REQSENT); 969 (*fp->parent->LayerDown)(fp->parent->object, fp); 970 } 971} 972 973void 974fsm2initial(struct fsm *fp) 975{ 976 if (fp->state == ST_STOPPED) 977 fsm_Close(fp); 978 if (fp->state > ST_INITIAL) 979 fsm_Down(fp); 980 if (fp->state > ST_INITIAL) 981 fsm_Close(fp); 982} 983