fsm.c revision 36285
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.27.2.35 1998/05/01 19:24:32 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 /* Force ourselves back to initial */ 124 fsm_Down(fp); 125 fsm_Close(fp); 126 } 127} 128 129void 130fsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode, 131 int maxcode, int maxcfg, int LogLevel, struct bundle *bundle, 132 struct link *l, const struct fsm_parent *parent, 133 struct fsm_callbacks *fn, const char *timer_names[3]) 134{ 135 fp->name = name; 136 fp->proto = proto; 137 fp->min_code = mincode; 138 fp->max_code = maxcode; 139 fp->state = fp->min_code > CODE_TERMACK ? ST_OPENED : ST_INITIAL; 140 fp->reqid = 1; 141 fp->restart = 1; 142 fp->maxconfig = maxcfg; 143 memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer); 144 memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer); 145 memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer); 146 fp->LogLevel = LogLevel; 147 fp->link = l; 148 fp->bundle = bundle; 149 fp->parent = parent; 150 fp->fn = fn; 151 fp->FsmTimer.name = timer_names[0]; 152 fp->OpenTimer.name = timer_names[1]; 153 fp->StoppedTimer.name = timer_names[2]; 154} 155 156static void 157NewState(struct fsm * fp, int new) 158{ 159 log_Printf(fp->LogLevel, "%s: State change %s --> %s\n", 160 fp->link->name, State2Nam(fp->state), State2Nam(new)); 161 if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING) 162 timer_Stop(&fp->StoppedTimer); 163 fp->state = new; 164 if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) { 165 timer_Stop(&fp->FsmTimer); 166 if (new == ST_STOPPED && fp->StoppedTimer.load) { 167 timer_Stop(&fp->StoppedTimer); 168 fp->StoppedTimer.func = StoppedTimeout; 169 fp->StoppedTimer.arg = (void *) fp; 170 timer_Start(&fp->StoppedTimer); 171 } 172 } 173} 174 175void 176fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count) 177{ 178 int plen; 179 struct fsmheader lh; 180 struct mbuf *bp; 181 182 if (log_IsKept(fp->LogLevel)) { 183 log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n", 184 fp->link->name, Code2Nam(code), id, State2Nam(fp->state)); 185 switch (code) { 186 case CODE_CONFIGREQ: 187 case CODE_CONFIGACK: 188 case CODE_CONFIGREJ: 189 case CODE_CONFIGNAK: 190 (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL); 191 if (count < sizeof(struct fsmconfig)) 192 log_Printf(fp->LogLevel, " [EMPTY]\n"); 193 break; 194 } 195 } 196 197 plen = sizeof(struct fsmheader) + count; 198 lh.code = code; 199 lh.id = id; 200 lh.length = htons(plen); 201 bp = mbuf_Alloc(plen, MB_FSM); 202 memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 203 if (count) 204 memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count); 205 log_DumpBp(LogDEBUG, "fsm_Output", bp); 206 hdlc_Output(fp->link, PRI_LINK, fp->proto, bp); 207} 208 209static void 210FsmOpenNow(void *v) 211{ 212 struct fsm *fp = (struct fsm *)v; 213 214 timer_Stop(&fp->OpenTimer); 215 if (fp->state <= ST_STOPPED) { 216 FsmInitRestartCounter(fp); 217 FsmSendConfigReq(fp); 218 NewState(fp, ST_REQSENT); 219 } 220} 221 222void 223fsm_Open(struct fsm * fp) 224{ 225 switch (fp->state) { 226 case ST_INITIAL: 227 NewState(fp, ST_STARTING); 228 (*fp->fn->LayerStart)(fp); 229 (*fp->parent->LayerStart)(fp->parent->object, fp); 230 break; 231 case ST_CLOSED: 232 if (fp->open_mode == OPEN_PASSIVE) { 233 NewState(fp, ST_STOPPED); 234 } else if (fp->open_mode > 0) { 235 if (fp->open_mode > 1) 236 log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n", 237 fp->link->name, fp->open_mode); 238 NewState(fp, ST_STOPPED); 239 timer_Stop(&fp->OpenTimer); 240 fp->OpenTimer.load = fp->open_mode * SECTICKS; 241 fp->OpenTimer.func = FsmOpenNow; 242 fp->OpenTimer.arg = (void *)fp; 243 timer_Start(&fp->OpenTimer); 244 } else 245 FsmOpenNow(fp); 246 break; 247 case ST_STOPPED: /* XXX: restart option */ 248 case ST_REQSENT: 249 case ST_ACKRCVD: 250 case ST_ACKSENT: 251 case ST_OPENED: /* XXX: restart option */ 252 break; 253 case ST_CLOSING: /* XXX: restart option */ 254 case ST_STOPPING: /* XXX: restart option */ 255 NewState(fp, ST_STOPPING); 256 break; 257 } 258} 259 260void 261fsm_Up(struct fsm * fp) 262{ 263 switch (fp->state) { 264 case ST_INITIAL: 265 log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n", 266 fp->link->name); 267 NewState(fp, ST_CLOSED); 268 break; 269 case ST_STARTING: 270 FsmInitRestartCounter(fp); 271 FsmSendConfigReq(fp); 272 NewState(fp, ST_REQSENT); 273 break; 274 default: 275 log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n", 276 fp->link->name, State2Nam(fp->state)); 277 break; 278 } 279} 280 281void 282fsm_Down(struct fsm *fp) 283{ 284 switch (fp->state) { 285 case ST_CLOSED: 286 NewState(fp, ST_INITIAL); 287 break; 288 case ST_CLOSING: 289 (*fp->fn->LayerFinish)(fp); 290 NewState(fp, ST_INITIAL); 291 (*fp->parent->LayerFinish)(fp->parent->object, fp); 292 break; 293 case ST_STOPPED: 294 NewState(fp, ST_STARTING); 295 (*fp->fn->LayerStart)(fp); 296 (*fp->parent->LayerStart)(fp->parent->object, fp); 297 break; 298 case ST_STOPPING: 299 case ST_REQSENT: 300 case ST_ACKRCVD: 301 case ST_ACKSENT: 302 NewState(fp, ST_STARTING); 303 break; 304 case ST_OPENED: 305 (*fp->fn->LayerDown)(fp); 306 NewState(fp, ST_STARTING); 307 (*fp->parent->LayerDown)(fp->parent->object, fp); 308 break; 309 } 310} 311 312void 313fsm_Close(struct fsm *fp) 314{ 315 switch (fp->state) { 316 case ST_STARTING: 317 (*fp->fn->LayerFinish)(fp); 318 NewState(fp, ST_INITIAL); 319 (*fp->parent->LayerFinish)(fp->parent->object, fp); 320 break; 321 case ST_STOPPED: 322 NewState(fp, ST_CLOSED); 323 break; 324 case ST_STOPPING: 325 NewState(fp, ST_CLOSING); 326 break; 327 case ST_OPENED: 328 (*fp->fn->LayerDown)(fp); 329 FsmInitRestartCounter(fp); 330 FsmSendTerminateReq(fp); 331 NewState(fp, ST_CLOSING); 332 (*fp->parent->LayerDown)(fp->parent->object, fp); 333 break; 334 case ST_REQSENT: 335 case ST_ACKRCVD: 336 case ST_ACKSENT: 337 FsmInitRestartCounter(fp); 338 FsmSendTerminateReq(fp); 339 NewState(fp, ST_CLOSING); 340 break; 341 } 342} 343 344/* 345 * Send functions 346 */ 347static void 348FsmSendConfigReq(struct fsm * fp) 349{ 350 if (--fp->maxconfig > 0) { 351 (*fp->fn->SendConfigReq)(fp); 352 timer_Start(&fp->FsmTimer); /* Start restart timer */ 353 fp->restart--; /* Decrement restart counter */ 354 } else { 355 fsm_Close(fp); 356 } 357} 358 359static void 360FsmSendTerminateReq(struct fsm *fp) 361{ 362 fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0); 363 (*fp->fn->SentTerminateReq)(fp); 364 timer_Start(&fp->FsmTimer); /* Start restart timer */ 365 fp->restart--; /* Decrement restart counter */ 366} 367 368/* 369 * Timeout actions 370 */ 371static void 372FsmTimeout(void *v) 373{ 374 struct fsm *fp = (struct fsm *)v; 375 376 if (fp->restart) { 377 switch (fp->state) { 378 case ST_CLOSING: 379 case ST_STOPPING: 380 FsmSendTerminateReq(fp); 381 break; 382 case ST_REQSENT: 383 case ST_ACKSENT: 384 FsmSendConfigReq(fp); 385 break; 386 case ST_ACKRCVD: 387 FsmSendConfigReq(fp); 388 NewState(fp, ST_REQSENT); 389 break; 390 } 391 timer_Start(&fp->FsmTimer); 392 } else { 393 switch (fp->state) { 394 case ST_CLOSING: 395 (*fp->fn->LayerFinish)(fp); 396 NewState(fp, ST_CLOSED); 397 (*fp->parent->LayerFinish)(fp->parent->object, fp); 398 break; 399 case ST_STOPPING: 400 (*fp->fn->LayerFinish)(fp); 401 NewState(fp, ST_STOPPED); 402 (*fp->parent->LayerFinish)(fp->parent->object, fp); 403 break; 404 case ST_REQSENT: /* XXX: 3p */ 405 case ST_ACKSENT: 406 case ST_ACKRCVD: 407 (*fp->fn->LayerFinish)(fp); 408 NewState(fp, ST_STOPPED); 409 (*fp->parent->LayerFinish)(fp->parent->object, fp); 410 break; 411 } 412 } 413} 414 415static void 416FsmInitRestartCounter(struct fsm * fp) 417{ 418 timer_Stop(&fp->FsmTimer); 419 fp->FsmTimer.func = FsmTimeout; 420 fp->FsmTimer.arg = (void *) fp; 421 (*fp->fn->InitRestartCounter)(fp); 422} 423 424/* 425 * Actions when receive packets 426 */ 427static void 428FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 429/* RCR */ 430{ 431 struct fsm_decode dec; 432 int plen, flen; 433 int ackaction = 0; 434 435 plen = mbuf_Length(bp); 436 flen = ntohs(lhp->length) - sizeof *lhp; 437 if (plen < flen) { 438 log_Printf(LogERROR, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n", 439 fp->link->name, plen, flen); 440 mbuf_Free(bp); 441 return; 442 } 443 444 /* 445 * Check and process easy case 446 */ 447 switch (fp->state) { 448 case ST_INITIAL: 449 case ST_STARTING: 450 log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n", 451 fp->link->name, State2Nam(fp->state)); 452 mbuf_Free(bp); 453 return; 454 case ST_CLOSED: 455 (*fp->fn->SendTerminateAck)(fp, lhp->id); 456 mbuf_Free(bp); 457 return; 458 case ST_CLOSING: 459 log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n", 460 fp->link->name, State2Nam(fp->state)); 461 case ST_STOPPING: 462 mbuf_Free(bp); 463 return; 464 } 465 466 dec.ackend = dec.ack; 467 dec.nakend = dec.nak; 468 dec.rejend = dec.rej; 469 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec); 470 if (flen < sizeof(struct fsmconfig)) 471 log_Printf(fp->LogLevel, " [EMPTY]\n"); 472 473 if (dec.nakend == dec.nak && dec.rejend == dec.rej) 474 ackaction = 1; 475 476 switch (fp->state) { 477 case ST_OPENED: 478 (*fp->fn->LayerDown)(fp); 479 FsmSendConfigReq(fp); 480 (*fp->parent->LayerDown)(fp->parent->object, fp); 481 break; 482 case ST_STOPPED: 483 FsmInitRestartCounter(fp); 484 FsmSendConfigReq(fp); 485 break; 486 } 487 488 if (dec.rejend != dec.rej) 489 fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej); 490 if (dec.nakend != dec.nak) 491 fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak); 492 if (ackaction) 493 fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack); 494 495 switch (fp->state) { 496 case ST_OPENED: 497 case ST_STOPPED: 498 if (ackaction) 499 NewState(fp, ST_ACKSENT); 500 else 501 NewState(fp, ST_REQSENT); 502 break; 503 case ST_REQSENT: 504 if (ackaction) 505 NewState(fp, ST_ACKSENT); 506 break; 507 case ST_ACKRCVD: 508 if (ackaction) { 509 NewState(fp, ST_OPENED); 510 if ((*fp->fn->LayerUp)(fp)) 511 (*fp->parent->LayerUp)(fp->parent->object, fp); 512 else { 513 (*fp->fn->LayerDown)(fp); 514 FsmInitRestartCounter(fp); 515 FsmSendTerminateReq(fp); 516 NewState(fp, ST_CLOSING); 517 } 518 } 519 break; 520 case ST_ACKSENT: 521 if (!ackaction) 522 NewState(fp, ST_REQSENT); 523 break; 524 } 525 mbuf_Free(bp); 526} 527 528static void 529FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 530/* RCA */ 531{ 532 switch (fp->state) { 533 case ST_CLOSED: 534 case ST_STOPPED: 535 (*fp->fn->SendTerminateAck)(fp, lhp->id); 536 break; 537 case ST_CLOSING: 538 case ST_STOPPING: 539 break; 540 case ST_REQSENT: 541 FsmInitRestartCounter(fp); 542 NewState(fp, ST_ACKRCVD); 543 break; 544 case ST_ACKRCVD: 545 FsmSendConfigReq(fp); 546 NewState(fp, ST_REQSENT); 547 break; 548 case ST_ACKSENT: 549 FsmInitRestartCounter(fp); 550 NewState(fp, ST_OPENED); 551 if ((*fp->fn->LayerUp)(fp)) 552 (*fp->parent->LayerUp)(fp->parent->object, fp); 553 else { 554 (*fp->fn->LayerDown)(fp); 555 FsmInitRestartCounter(fp); 556 FsmSendTerminateReq(fp); 557 NewState(fp, ST_CLOSING); 558 } 559 break; 560 case ST_OPENED: 561 (*fp->fn->LayerDown)(fp); 562 FsmSendConfigReq(fp); 563 NewState(fp, ST_REQSENT); 564 (*fp->parent->LayerDown)(fp->parent->object, fp); 565 break; 566 } 567 mbuf_Free(bp); 568} 569 570static void 571FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 572/* RCN */ 573{ 574 struct fsm_decode dec; 575 int plen, flen; 576 577 plen = mbuf_Length(bp); 578 flen = ntohs(lhp->length) - sizeof *lhp; 579 if (plen < flen) { 580 mbuf_Free(bp); 581 return; 582 } 583 584 /* 585 * Check and process easy case 586 */ 587 switch (fp->state) { 588 case ST_INITIAL: 589 case ST_STARTING: 590 log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n", 591 fp->link->name, State2Nam(fp->state)); 592 mbuf_Free(bp); 593 return; 594 case ST_CLOSED: 595 case ST_STOPPED: 596 (*fp->fn->SendTerminateAck)(fp, lhp->id); 597 mbuf_Free(bp); 598 return; 599 case ST_CLOSING: 600 case ST_STOPPING: 601 mbuf_Free(bp); 602 return; 603 } 604 605 dec.ackend = dec.ack; 606 dec.nakend = dec.nak; 607 dec.rejend = dec.rej; 608 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec); 609 if (flen < sizeof(struct fsmconfig)) 610 log_Printf(fp->LogLevel, " [EMPTY]\n"); 611 612 switch (fp->state) { 613 case ST_REQSENT: 614 case ST_ACKSENT: 615 FsmInitRestartCounter(fp); 616 FsmSendConfigReq(fp); 617 break; 618 case ST_OPENED: 619 (*fp->fn->LayerDown)(fp); 620 FsmSendConfigReq(fp); 621 NewState(fp, ST_REQSENT); 622 (*fp->parent->LayerDown)(fp->parent->object, fp); 623 break; 624 case ST_ACKRCVD: 625 FsmSendConfigReq(fp); 626 NewState(fp, ST_REQSENT); 627 break; 628 } 629 630 mbuf_Free(bp); 631} 632 633static void 634FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 635/* RTR */ 636{ 637 switch (fp->state) { 638 case ST_INITIAL: 639 case ST_STARTING: 640 log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n", 641 fp->link->name, State2Nam(fp->state)); 642 break; 643 case ST_CLOSED: 644 case ST_STOPPED: 645 case ST_CLOSING: 646 case ST_STOPPING: 647 case ST_REQSENT: 648 (*fp->fn->SendTerminateAck)(fp, lhp->id); 649 break; 650 case ST_ACKRCVD: 651 case ST_ACKSENT: 652 (*fp->fn->SendTerminateAck)(fp, lhp->id); 653 NewState(fp, ST_REQSENT); 654 break; 655 case ST_OPENED: 656 (*fp->fn->LayerDown)(fp); 657 (*fp->fn->SendTerminateAck)(fp, lhp->id); 658 timer_Start(&fp->FsmTimer); /* Start restart timer */ 659 fp->restart = 0; 660 NewState(fp, ST_STOPPING); 661 (*fp->parent->LayerDown)(fp->parent->object, fp); 662 break; 663 } 664 mbuf_Free(bp); 665} 666 667static void 668FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 669/* RTA */ 670{ 671 switch (fp->state) { 672 case ST_CLOSING: 673 (*fp->fn->LayerFinish)(fp); 674 NewState(fp, ST_CLOSED); 675 (*fp->parent->LayerFinish)(fp->parent->object, fp); 676 break; 677 case ST_STOPPING: 678 (*fp->fn->LayerFinish)(fp); 679 NewState(fp, ST_STOPPED); 680 (*fp->parent->LayerFinish)(fp->parent->object, fp); 681 break; 682 case ST_ACKRCVD: 683 NewState(fp, ST_REQSENT); 684 break; 685 case ST_OPENED: 686 (*fp->fn->LayerDown)(fp); 687 FsmSendConfigReq(fp); 688 NewState(fp, ST_REQSENT); 689 (*fp->parent->LayerDown)(fp->parent->object, fp); 690 break; 691 } 692 mbuf_Free(bp); 693} 694 695static void 696FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 697/* RCJ */ 698{ 699 struct fsm_decode dec; 700 int plen, flen; 701 702 plen = mbuf_Length(bp); 703 flen = ntohs(lhp->length) - sizeof *lhp; 704 if (plen < flen) { 705 mbuf_Free(bp); 706 return; 707 } 708 709 /* 710 * Check and process easy case 711 */ 712 switch (fp->state) { 713 case ST_INITIAL: 714 case ST_STARTING: 715 log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n", 716 fp->link->name, State2Nam(fp->state)); 717 mbuf_Free(bp); 718 return; 719 case ST_CLOSED: 720 case ST_STOPPED: 721 (*fp->fn->SendTerminateAck)(fp, lhp->id); 722 mbuf_Free(bp); 723 return; 724 case ST_CLOSING: 725 case ST_STOPPING: 726 mbuf_Free(bp); 727 return; 728 } 729 730 dec.ackend = dec.ack; 731 dec.nakend = dec.nak; 732 dec.rejend = dec.rej; 733 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec); 734 if (flen < sizeof(struct fsmconfig)) 735 log_Printf(fp->LogLevel, " [EMPTY]\n"); 736 737 switch (fp->state) { 738 case ST_REQSENT: 739 case ST_ACKSENT: 740 FsmInitRestartCounter(fp); 741 FsmSendConfigReq(fp); 742 break; 743 case ST_OPENED: 744 (*fp->fn->LayerDown)(fp); 745 FsmSendConfigReq(fp); 746 NewState(fp, ST_REQSENT); 747 (*fp->parent->LayerDown)(fp->parent->object, fp); 748 break; 749 case ST_ACKRCVD: 750 FsmSendConfigReq(fp); 751 NewState(fp, ST_REQSENT); 752 break; 753 } 754 mbuf_Free(bp); 755} 756 757static void 758FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 759{ 760 mbuf_Free(bp); 761} 762 763static void 764FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 765{ 766 struct physical *p = link2physical(fp->link); 767 u_short *sp, proto; 768 769 sp = (u_short *) MBUF_CTOP(bp); 770 proto = ntohs(*sp); 771 log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n", 772 fp->link->name, proto, hdlc_Protocol2Nam(proto)); 773 774 switch (proto) { 775 case PROTO_LQR: 776 if (p) 777 lqr_Stop(p, LQM_LQR); 778 else 779 log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n", 780 fp->link->name); 781 break; 782 case PROTO_CCP: 783 if (fp->proto == PROTO_LCP) { 784 fp = &fp->link->ccp.fsm; 785 (*fp->fn->LayerFinish)(fp); 786 switch (fp->state) { 787 case ST_CLOSED: 788 case ST_CLOSING: 789 NewState(fp, ST_CLOSED); 790 default: 791 NewState(fp, ST_STOPPED); 792 break; 793 } 794 (*fp->parent->LayerFinish)(fp->parent->object, fp); 795 } 796 break; 797 case PROTO_MP: 798 if (fp->proto == PROTO_LCP) { 799 struct lcp *lcp = fsm2lcp(fp); 800 801 if (lcp->want_mrru && lcp->his_mrru) { 802 log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n", 803 fp->link->name); 804 fsm_Close(fp); 805 } 806 } 807 break; 808 } 809 mbuf_Free(bp); 810} 811 812static void 813FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 814{ 815 struct lcp *lcp = fsm2lcp(fp); 816 u_char *cp; 817 u_int32_t magic; 818 819 if (lcp) { 820 cp = MBUF_CTOP(bp); 821 magic = ntohl(*(u_int32_t *)cp); 822 if (magic != lcp->his_magic) { 823 log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n", 824 fp->link->name); 825 /* XXX: We should send terminate request */ 826 } 827 if (fp->state == ST_OPENED) { 828 *(u_int32_t *)cp = htonl(lcp->want_magic); /* local magic */ 829 fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp)); 830 } 831 } 832 mbuf_Free(bp); 833} 834 835static void 836FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 837{ 838 struct lcp *lcp = fsm2lcp(fp); 839 u_int32_t magic; 840 841 if (lcp) { 842 magic = ntohl(*(u_int32_t *)MBUF_CTOP(bp)); 843 /* Tolerate echo replies with either magic number */ 844 if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) { 845 log_Printf(LogWARN, 846 "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n", 847 fp->link->name, lcp->his_magic, magic); 848 /* 849 * XXX: We should send terminate request. But poor implementations may 850 * die as a result. 851 */ 852 } 853 lqr_RecvEcho(fp, bp); 854 } 855 mbuf_Free(bp); 856} 857 858static void 859FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 860{ 861 mbuf_Free(bp); 862} 863 864static void 865FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 866{ 867 mbuf_Free(bp); 868} 869 870static void 871FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 872{ 873 mbuf_Free(bp); 874} 875 876static void 877FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 878{ 879 (*fp->fn->RecvResetReq)(fp); 880 /* 881 * All sendable compressed packets are queued in the PRI_NORMAL modem 882 * output queue.... dump 'em to the priority queue so that they arrive 883 * at the peer before our ResetAck. 884 */ 885 link_SequenceQueue(fp->link); 886 fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0); 887 mbuf_Free(bp); 888} 889 890static void 891FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 892{ 893 (*fp->fn->RecvResetAck)(fp, lhp->id); 894 mbuf_Free(bp); 895} 896 897void 898fsm_Input(struct fsm *fp, struct mbuf *bp) 899{ 900 int len; 901 struct fsmheader *lhp; 902 const struct fsmcodedesc *codep; 903 904 len = mbuf_Length(bp); 905 if (len < sizeof(struct fsmheader)) { 906 mbuf_Free(bp); 907 return; 908 } 909 lhp = (struct fsmheader *) MBUF_CTOP(bp); 910 if (lhp->code < fp->min_code || lhp->code > fp->max_code || 911 lhp->code > sizeof FsmCodes / sizeof *FsmCodes) { 912 /* 913 * Use a private id. This is really a response-type packet, but we 914 * MUST send a unique id for each REQ.... 915 */ 916 static u_char id; 917 fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt); 918 mbuf_Free(bp); 919 return; 920 } 921 bp->offset += sizeof(struct fsmheader); 922 bp->cnt -= sizeof(struct fsmheader); 923 924 codep = FsmCodes + lhp->code - 1; 925 if (lhp->id != fp->reqid && codep->check_reqid && 926 Enabled(fp->bundle, OPT_IDCHECK)) { 927 log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n", 928 fp->link->name, codep->name, lhp->id, fp->reqid); 929 return; 930 } 931 932 log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n", 933 fp->link->name, codep->name, lhp->id, State2Nam(fp->state)); 934 935 if (log_IsKept(LogDEBUG)) 936 mbuf_Log(); 937 938 if (codep->inc_reqid && (lhp->id == fp->reqid || 939 (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid))) 940 fp->reqid++; /* That's the end of that ``exchange''.... */ 941 942 (*codep->recv)(fp, lhp, bp); 943 944 if (log_IsKept(LogDEBUG)) 945 mbuf_Log(); 946} 947 948void 949fsm_NullRecvResetReq(struct fsm *fp) 950{ 951 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n", 952 fp->link->name); 953} 954 955void 956fsm_NullRecvResetAck(struct fsm *fp, u_char id) 957{ 958 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n", 959 fp->link->name); 960} 961