fsm.c revision 44359
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.39 1999/02/26 21:28:11 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 *, int); 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 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->more.reqs = fp->more.naks = fp->more.rejs = 1; 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, FSM_REQ_TIMER); 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, FSM_REQ_TIMER); 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 /* This TLF contradicts the RFC (1661), which ``misses it out'' ! */ 306 (*fp->fn->LayerFinish)(fp); 307 NewState(fp, ST_INITIAL); 308 (*fp->parent->LayerFinish)(fp->parent->object, fp); 309 break; 310 case ST_STOPPED: 311 NewState(fp, ST_STARTING); 312 (*fp->fn->LayerStart)(fp); 313 (*fp->parent->LayerStart)(fp->parent->object, fp); 314 break; 315 case ST_STOPPING: 316 case ST_REQSENT: 317 case ST_ACKRCVD: 318 case ST_ACKSENT: 319 NewState(fp, ST_STARTING); 320 break; 321 case ST_OPENED: 322 (*fp->fn->LayerDown)(fp); 323 NewState(fp, ST_STARTING); 324 (*fp->parent->LayerDown)(fp->parent->object, fp); 325 break; 326 } 327} 328 329void 330fsm_Close(struct fsm *fp) 331{ 332 switch (fp->state) { 333 case ST_STARTING: 334 (*fp->fn->LayerFinish)(fp); 335 NewState(fp, ST_INITIAL); 336 (*fp->parent->LayerFinish)(fp->parent->object, fp); 337 break; 338 case ST_STOPPED: 339 NewState(fp, ST_CLOSED); 340 break; 341 case ST_STOPPING: 342 NewState(fp, ST_CLOSING); 343 break; 344 case ST_OPENED: 345 (*fp->fn->LayerDown)(fp); 346 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 347 FsmSendTerminateReq(fp); 348 NewState(fp, ST_CLOSING); 349 (*fp->parent->LayerDown)(fp->parent->object, fp); 350 break; 351 case ST_REQSENT: 352 case ST_ACKRCVD: 353 case ST_ACKSENT: 354 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 355 FsmSendTerminateReq(fp); 356 NewState(fp, ST_CLOSING); 357 break; 358 } 359} 360 361/* 362 * Send functions 363 */ 364static void 365FsmSendConfigReq(struct fsm * fp) 366{ 367 if (fp->more.reqs-- > 0 && fp->restart-- > 0) { 368 (*fp->fn->SendConfigReq)(fp); 369 timer_Start(&fp->FsmTimer); /* Start restart timer */ 370 } else { 371 if (fp->more.reqs < 0) 372 log_Printf(LogPHASE, "%s: Too many %s REQs sent - abandoning " 373 "negotiation\n", fp->link->name, fp->name); 374 fsm_Close(fp); 375 } 376} 377 378static void 379FsmSendTerminateReq(struct fsm *fp) 380{ 381 fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0); 382 (*fp->fn->SentTerminateReq)(fp); 383 timer_Start(&fp->FsmTimer); /* Start restart timer */ 384 fp->restart--; /* Decrement restart counter */ 385} 386 387/* 388 * Timeout actions 389 */ 390static void 391FsmTimeout(void *v) 392{ 393 struct fsm *fp = (struct fsm *)v; 394 395 if (fp->restart) { 396 switch (fp->state) { 397 case ST_CLOSING: 398 case ST_STOPPING: 399 FsmSendTerminateReq(fp); 400 break; 401 case ST_REQSENT: 402 case ST_ACKSENT: 403 FsmSendConfigReq(fp); 404 break; 405 case ST_ACKRCVD: 406 FsmSendConfigReq(fp); 407 NewState(fp, ST_REQSENT); 408 break; 409 } 410 timer_Start(&fp->FsmTimer); 411 } else { 412 switch (fp->state) { 413 case ST_CLOSING: 414 (*fp->fn->LayerFinish)(fp); 415 NewState(fp, ST_CLOSED); 416 (*fp->parent->LayerFinish)(fp->parent->object, fp); 417 break; 418 case ST_STOPPING: 419 (*fp->fn->LayerFinish)(fp); 420 NewState(fp, ST_STOPPED); 421 (*fp->parent->LayerFinish)(fp->parent->object, fp); 422 break; 423 case ST_REQSENT: /* XXX: 3p */ 424 case ST_ACKSENT: 425 case ST_ACKRCVD: 426 (*fp->fn->LayerFinish)(fp); 427 NewState(fp, ST_STOPPED); 428 (*fp->parent->LayerFinish)(fp->parent->object, fp); 429 break; 430 } 431 } 432} 433 434static void 435FsmInitRestartCounter(struct fsm *fp, int what) 436{ 437 timer_Stop(&fp->FsmTimer); 438 fp->FsmTimer.func = FsmTimeout; 439 fp->FsmTimer.arg = (void *)fp; 440 (*fp->fn->InitRestartCounter)(fp, what); 441} 442 443/* 444 * Actions when receive packets 445 */ 446static void 447FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 448/* RCR */ 449{ 450 struct fsm_decode dec; 451 int plen, flen; 452 int ackaction = 0; 453 454 plen = mbuf_Length(bp); 455 flen = ntohs(lhp->length) - sizeof *lhp; 456 if (plen < flen) { 457 log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n", 458 fp->link->name, plen, flen); 459 mbuf_Free(bp); 460 return; 461 } 462 463 /* 464 * Check and process easy case 465 */ 466 switch (fp->state) { 467 case ST_INITIAL: 468 if (fp->proto == PROTO_CCP && fp->link->lcp.fsm.state == ST_OPENED) { 469 /* 470 * ccp_SetOpenMode() leaves us in initial if we're disabling 471 * & denying everything. This is a bit smelly, we know that 472 * ``bp'' really has ``fsmheader'' in front of it, and CCP_PROTO 473 * in front of that. CCP_PROTO isn't compressed either 'cos it 474 * doesn't begin with 0x00.... 475 */ 476 bp->offset -= sizeof(struct fsmheader) + 2; 477 bp->cnt += sizeof(struct fsmheader) + 2; 478 lcp_SendProtoRej(&fp->link->lcp, MBUF_CTOP(bp), bp->cnt); 479 mbuf_Free(bp); 480 return; 481 } 482 /* Drop through */ 483 case ST_STARTING: 484 log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n", 485 fp->link->name, State2Nam(fp->state)); 486 mbuf_Free(bp); 487 return; 488 case ST_CLOSED: 489 (*fp->fn->SendTerminateAck)(fp, lhp->id); 490 mbuf_Free(bp); 491 return; 492 case ST_CLOSING: 493 log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n", 494 fp->link->name, State2Nam(fp->state)); 495 case ST_STOPPING: 496 mbuf_Free(bp); 497 return; 498 case ST_OPENED: 499 (*fp->fn->LayerDown)(fp); 500 (*fp->parent->LayerDown)(fp->parent->object, fp); 501 break; 502 } 503 504 dec.ackend = dec.ack; 505 dec.nakend = dec.nak; 506 dec.rejend = dec.rej; 507 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec); 508 if (flen < sizeof(struct fsmconfig)) 509 log_Printf(fp->LogLevel, " [EMPTY]\n"); 510 511 if (dec.nakend == dec.nak && dec.rejend == dec.rej) 512 ackaction = 1; 513 514 switch (fp->state) { 515 case ST_STOPPED: 516 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 517 /* Fall through */ 518 519 case ST_OPENED: 520 FsmSendConfigReq(fp); 521 break; 522 } 523 524 if (dec.rejend != dec.rej) 525 fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej); 526 if (dec.nakend != dec.nak) 527 fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak); 528 if (ackaction) 529 fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack); 530 531 switch (fp->state) { 532 case ST_STOPPED: 533 /* 534 * According to the RFC (1661) state transition table, a TLS isn't 535 * required for a RCR when state == ST_STOPPED, but the RFC 536 * must be wrong as TLS hasn't yet been called (since the last TLF) 537 */ 538 (*fp->fn->LayerStart)(fp); 539 (*fp->parent->LayerStart)(fp->parent->object, fp); 540 /* Fall through */ 541 542 case ST_OPENED: 543 if (ackaction) 544 NewState(fp, ST_ACKSENT); 545 else 546 NewState(fp, ST_REQSENT); 547 break; 548 case ST_REQSENT: 549 if (ackaction) 550 NewState(fp, ST_ACKSENT); 551 break; 552 case ST_ACKRCVD: 553 if (ackaction) { 554 NewState(fp, ST_OPENED); 555 if ((*fp->fn->LayerUp)(fp)) 556 (*fp->parent->LayerUp)(fp->parent->object, fp); 557 else { 558 (*fp->fn->LayerDown)(fp); 559 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 560 FsmSendTerminateReq(fp); 561 NewState(fp, ST_CLOSING); 562 } 563 } 564 break; 565 case ST_ACKSENT: 566 if (!ackaction) 567 NewState(fp, ST_REQSENT); 568 break; 569 } 570 mbuf_Free(bp); 571 572 if (dec.rejend != dec.rej && --fp->more.rejs <= 0) { 573 log_Printf(LogPHASE, "%s: Too many %s REJs sent - abandoning negotiation\n", 574 fp->link->name, fp->name); 575 fsm_Close(fp); 576 } 577 578 if (dec.nakend != dec.nak && --fp->more.naks <= 0) { 579 fsm_Close(fp); 580 log_Printf(LogPHASE, "%s: Too many %s NAKs sent - abandoning negotiation\n", 581 fp->link->name, fp->name); 582 fsm_Close(fp); 583 } 584} 585 586static void 587FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 588/* RCA */ 589{ 590 switch (fp->state) { 591 case ST_CLOSED: 592 case ST_STOPPED: 593 (*fp->fn->SendTerminateAck)(fp, lhp->id); 594 break; 595 case ST_CLOSING: 596 case ST_STOPPING: 597 break; 598 case ST_REQSENT: 599 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 600 NewState(fp, ST_ACKRCVD); 601 break; 602 case ST_ACKRCVD: 603 FsmSendConfigReq(fp); 604 NewState(fp, ST_REQSENT); 605 break; 606 case ST_ACKSENT: 607 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 608 NewState(fp, ST_OPENED); 609 if ((*fp->fn->LayerUp)(fp)) 610 (*fp->parent->LayerUp)(fp->parent->object, fp); 611 else { 612 (*fp->fn->LayerDown)(fp); 613 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 614 FsmSendTerminateReq(fp); 615 NewState(fp, ST_CLOSING); 616 } 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 } 625 mbuf_Free(bp); 626} 627 628static void 629FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 630/* RCN */ 631{ 632 struct fsm_decode dec; 633 int plen, flen; 634 635 plen = mbuf_Length(bp); 636 flen = ntohs(lhp->length) - sizeof *lhp; 637 if (plen < flen) { 638 mbuf_Free(bp); 639 return; 640 } 641 642 /* 643 * Check and process easy case 644 */ 645 switch (fp->state) { 646 case ST_INITIAL: 647 case ST_STARTING: 648 log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n", 649 fp->link->name, State2Nam(fp->state)); 650 mbuf_Free(bp); 651 return; 652 case ST_CLOSED: 653 case ST_STOPPED: 654 (*fp->fn->SendTerminateAck)(fp, lhp->id); 655 mbuf_Free(bp); 656 return; 657 case ST_CLOSING: 658 case ST_STOPPING: 659 mbuf_Free(bp); 660 return; 661 } 662 663 dec.ackend = dec.ack; 664 dec.nakend = dec.nak; 665 dec.rejend = dec.rej; 666 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec); 667 if (flen < sizeof(struct fsmconfig)) 668 log_Printf(fp->LogLevel, " [EMPTY]\n"); 669 670 switch (fp->state) { 671 case ST_REQSENT: 672 case ST_ACKSENT: 673 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 674 FsmSendConfigReq(fp); 675 break; 676 case ST_OPENED: 677 (*fp->fn->LayerDown)(fp); 678 FsmSendConfigReq(fp); 679 NewState(fp, ST_REQSENT); 680 (*fp->parent->LayerDown)(fp->parent->object, fp); 681 break; 682 case ST_ACKRCVD: 683 FsmSendConfigReq(fp); 684 NewState(fp, ST_REQSENT); 685 break; 686 } 687 688 mbuf_Free(bp); 689} 690 691static void 692FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 693/* RTR */ 694{ 695 switch (fp->state) { 696 case ST_INITIAL: 697 case ST_STARTING: 698 log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n", 699 fp->link->name, State2Nam(fp->state)); 700 break; 701 case ST_CLOSED: 702 case ST_STOPPED: 703 case ST_CLOSING: 704 case ST_STOPPING: 705 case ST_REQSENT: 706 (*fp->fn->SendTerminateAck)(fp, lhp->id); 707 break; 708 case ST_ACKRCVD: 709 case ST_ACKSENT: 710 (*fp->fn->SendTerminateAck)(fp, lhp->id); 711 NewState(fp, ST_REQSENT); 712 break; 713 case ST_OPENED: 714 (*fp->fn->LayerDown)(fp); 715 (*fp->fn->SendTerminateAck)(fp, lhp->id); 716 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 717 timer_Start(&fp->FsmTimer); /* Start restart timer */ 718 fp->restart = 0; 719 NewState(fp, ST_STOPPING); 720 (*fp->parent->LayerDown)(fp->parent->object, fp); 721 /* A delayed ST_STOPPED is now scheduled */ 722 break; 723 } 724 mbuf_Free(bp); 725} 726 727static void 728FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 729/* RTA */ 730{ 731 switch (fp->state) { 732 case ST_CLOSING: 733 (*fp->fn->LayerFinish)(fp); 734 NewState(fp, ST_CLOSED); 735 (*fp->parent->LayerFinish)(fp->parent->object, fp); 736 break; 737 case ST_STOPPING: 738 (*fp->fn->LayerFinish)(fp); 739 NewState(fp, ST_STOPPED); 740 (*fp->parent->LayerFinish)(fp->parent->object, fp); 741 break; 742 case ST_ACKRCVD: 743 NewState(fp, ST_REQSENT); 744 break; 745 case ST_OPENED: 746 (*fp->fn->LayerDown)(fp); 747 FsmSendConfigReq(fp); 748 NewState(fp, ST_REQSENT); 749 (*fp->parent->LayerDown)(fp->parent->object, fp); 750 break; 751 } 752 mbuf_Free(bp); 753} 754 755static void 756FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 757/* RCJ */ 758{ 759 struct fsm_decode dec; 760 int plen, flen; 761 762 plen = mbuf_Length(bp); 763 flen = ntohs(lhp->length) - sizeof *lhp; 764 if (plen < flen) { 765 mbuf_Free(bp); 766 return; 767 } 768 769 /* 770 * Check and process easy case 771 */ 772 switch (fp->state) { 773 case ST_INITIAL: 774 case ST_STARTING: 775 log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n", 776 fp->link->name, State2Nam(fp->state)); 777 mbuf_Free(bp); 778 return; 779 case ST_CLOSED: 780 case ST_STOPPED: 781 (*fp->fn->SendTerminateAck)(fp, lhp->id); 782 mbuf_Free(bp); 783 return; 784 case ST_CLOSING: 785 case ST_STOPPING: 786 mbuf_Free(bp); 787 return; 788 } 789 790 dec.ackend = dec.ack; 791 dec.nakend = dec.nak; 792 dec.rejend = dec.rej; 793 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec); 794 if (flen < sizeof(struct fsmconfig)) 795 log_Printf(fp->LogLevel, " [EMPTY]\n"); 796 797 switch (fp->state) { 798 case ST_REQSENT: 799 case ST_ACKSENT: 800 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 801 FsmSendConfigReq(fp); 802 break; 803 case ST_OPENED: 804 (*fp->fn->LayerDown)(fp); 805 FsmSendConfigReq(fp); 806 NewState(fp, ST_REQSENT); 807 (*fp->parent->LayerDown)(fp->parent->object, fp); 808 break; 809 case ST_ACKRCVD: 810 FsmSendConfigReq(fp); 811 NewState(fp, ST_REQSENT); 812 break; 813 } 814 mbuf_Free(bp); 815} 816 817static void 818FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 819{ 820 mbuf_Free(bp); 821} 822 823static void 824FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 825{ 826 struct physical *p = link2physical(fp->link); 827 u_short *sp, proto; 828 829 sp = (u_short *)MBUF_CTOP(bp); 830 proto = ntohs(*sp); 831 log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n", 832 fp->link->name, proto, hdlc_Protocol2Nam(proto)); 833 834 switch (proto) { 835 case PROTO_LQR: 836 if (p) 837 lqr_Stop(p, LQM_LQR); 838 else 839 log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n", 840 fp->link->name); 841 break; 842 case PROTO_CCP: 843 if (fp->proto == PROTO_LCP) { 844 fp = &fp->link->ccp.fsm; 845 /* Despite the RFC (1661), don't do an out-of-place TLF */ 846 /* (*fp->fn->LayerFinish)(fp); */ 847 switch (fp->state) { 848 case ST_CLOSED: 849 case ST_CLOSING: 850 NewState(fp, ST_CLOSED); 851 default: 852 NewState(fp, ST_STOPPED); 853 break; 854 } 855 /* See above */ 856 /* (*fp->parent->LayerFinish)(fp->parent->object, fp); */ 857 } 858 break; 859 case PROTO_MP: 860 if (fp->proto == PROTO_LCP) { 861 struct lcp *lcp = fsm2lcp(fp); 862 863 if (lcp->want_mrru && lcp->his_mrru) { 864 log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n", 865 fp->link->name); 866 fsm_Close(fp); 867 } 868 } 869 break; 870 } 871 mbuf_Free(bp); 872} 873 874static void 875FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 876{ 877 struct lcp *lcp = fsm2lcp(fp); 878 u_char *cp; 879 u_int32_t magic; 880 881 if (lcp) { 882 cp = MBUF_CTOP(bp); 883 ua_ntohl(cp, &magic); 884 if (magic != lcp->his_magic) { 885 log_Printf(fp->LogLevel, "%s: RecvEchoReq: Error: His magic is bad!!\n", 886 fp->link->name); 887 /* XXX: We should send terminate request */ 888 } 889 if (fp->state == ST_OPENED) { 890 ua_htonl(&lcp->want_magic, cp); /* local magic */ 891 fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, mbuf_Length(bp)); 892 } 893 } 894 mbuf_Free(bp); 895} 896 897static void 898FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 899{ 900 struct lcp *lcp = fsm2lcp(fp); 901 u_int32_t magic; 902 903 if (lcp) { 904 ua_ntohl(MBUF_CTOP(bp), &magic); 905 /* Tolerate echo replies with either magic number */ 906 if (magic != 0 && magic != lcp->his_magic && magic != lcp->want_magic) { 907 log_Printf(LogWARN, 908 "%s: RecvEchoRep: Bad magic: expected 0x%08x, got: 0x%08x\n", 909 fp->link->name, lcp->his_magic, magic); 910 /* 911 * XXX: We should send terminate request. But poor implementations may 912 * die as a result. 913 */ 914 } 915 lqr_RecvEcho(fp, bp); 916 } 917 mbuf_Free(bp); 918} 919 920static void 921FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 922{ 923 mbuf_Free(bp); 924} 925 926static void 927FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 928{ 929 mbuf_Free(bp); 930} 931 932static void 933FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp) 934{ 935 mbuf_Free(bp); 936} 937 938static void 939FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 940{ 941 (*fp->fn->RecvResetReq)(fp); 942 /* 943 * All sendable compressed packets are queued in the PRI_NORMAL modem 944 * output queue.... dump 'em to the priority queue so that they arrive 945 * at the peer before our ResetAck. 946 */ 947 link_SequenceQueue(fp->link); 948 fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0); 949 mbuf_Free(bp); 950} 951 952static void 953FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 954{ 955 (*fp->fn->RecvResetAck)(fp, lhp->id); 956 mbuf_Free(bp); 957} 958 959void 960fsm_Input(struct fsm *fp, struct mbuf *bp) 961{ 962 int len; 963 struct fsmheader *lhp; 964 const struct fsmcodedesc *codep; 965 966 len = mbuf_Length(bp); 967 if (len < sizeof(struct fsmheader)) { 968 mbuf_Free(bp); 969 return; 970 } 971 lhp = (struct fsmheader *) MBUF_CTOP(bp); 972 if (lhp->code < fp->min_code || lhp->code > fp->max_code || 973 lhp->code > sizeof FsmCodes / sizeof *FsmCodes) { 974 /* 975 * Use a private id. This is really a response-type packet, but we 976 * MUST send a unique id for each REQ.... 977 */ 978 static u_char id; 979 980 fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->cnt); 981 mbuf_Free(bp); 982 return; 983 } 984 bp->offset += sizeof(struct fsmheader); 985 bp->cnt -= sizeof(struct fsmheader); 986 987 codep = FsmCodes + lhp->code - 1; 988 if (lhp->id != fp->reqid && codep->check_reqid && 989 Enabled(fp->bundle, OPT_IDCHECK)) { 990 log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n", 991 fp->link->name, codep->name, lhp->id, fp->reqid); 992 return; 993 } 994 995 log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n", 996 fp->link->name, codep->name, lhp->id, State2Nam(fp->state)); 997 998 if (log_IsKept(LogDEBUG)) 999 mbuf_Log(); 1000 1001 if (codep->inc_reqid && (lhp->id == fp->reqid || 1002 (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid))) 1003 fp->reqid++; /* That's the end of that ``exchange''.... */ 1004 1005 (*codep->recv)(fp, lhp, bp); 1006 1007 if (log_IsKept(LogDEBUG)) 1008 mbuf_Log(); 1009} 1010 1011void 1012fsm_NullRecvResetReq(struct fsm *fp) 1013{ 1014 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n", 1015 fp->link->name); 1016} 1017 1018void 1019fsm_NullRecvResetAck(struct fsm *fp, u_char id) 1020{ 1021 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n", 1022 fp->link->name); 1023} 1024 1025void 1026fsm_Reopen(struct fsm *fp) 1027{ 1028 if (fp->state == ST_OPENED) { 1029 (*fp->fn->LayerDown)(fp); 1030 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 1031 FsmSendConfigReq(fp); 1032 NewState(fp, ST_REQSENT); 1033 (*fp->parent->LayerDown)(fp->parent->object, fp); 1034 } 1035} 1036 1037void 1038fsm2initial(struct fsm *fp) 1039{ 1040 timer_Stop(&fp->FsmTimer); 1041 timer_Stop(&fp->OpenTimer); 1042 timer_Stop(&fp->StoppedTimer); 1043 if (fp->state == ST_STOPPED) 1044 fsm_Close(fp); 1045 if (fp->state > ST_INITIAL) 1046 fsm_Down(fp); 1047 if (fp->state > ST_INITIAL) 1048 fsm_Close(fp); 1049} 1050