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