fsm.c revision 93420
1258945Sroberto/*- 2280849Scy * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 3258945Sroberto * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 4258945Sroberto * Internet Initiative Japan, Inc (IIJ) 5258945Sroberto * All rights reserved. 6258945Sroberto * 7258945Sroberto * Redistribution and use in source and binary forms, with or without 8258945Sroberto * modification, are permitted provided that the following conditions 9258945Sroberto * are met: 10258945Sroberto * 1. Redistributions of source code must retain the above copyright 11258945Sroberto * notice, this list of conditions and the following disclaimer. 12258945Sroberto * 2. Redistributions in binary form must reproduce the above copyright 13258945Sroberto * notice, this list of conditions and the following disclaimer in the 14258945Sroberto * documentation and/or other materials provided with the distribution. 15258945Sroberto * 16258945Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17258945Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18280849Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19258945Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20258945Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21258945Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22258945Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23280849Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24280849Scy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25280849Scy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26258945Sroberto * SUCH DAMAGE. 27258945Sroberto * 28258945Sroberto * $FreeBSD: head/usr.sbin/ppp/fsm.c 93420 2002-03-30 12:47:29Z brian $ 29258945Sroberto */ 30258945Sroberto 31258945Sroberto#include <sys/param.h> 32258945Sroberto#include <netinet/in.h> 33258945Sroberto#include <netinet/in_systm.h> 34258945Sroberto#include <netinet/ip.h> 35258945Sroberto#include <sys/socket.h> 36258945Sroberto#include <sys/un.h> 37258945Sroberto 38258945Sroberto#include <string.h> 39258945Sroberto#include <termios.h> 40258945Sroberto 41258945Sroberto#include "layer.h" 42258945Sroberto#include "ua.h" 43258945Sroberto#include "mbuf.h" 44258945Sroberto#include "log.h" 45258945Sroberto#include "defs.h" 46280849Scy#include "timer.h" 47280849Scy#include "fsm.h" 48258945Sroberto#include "iplist.h" 49258945Sroberto#include "lqr.h" 50258945Sroberto#include "hdlc.h" 51258945Sroberto#include "throughput.h" 52258945Sroberto#include "slcompress.h" 53258945Sroberto#include "ncpaddr.h" 54258945Sroberto#include "ip.h" 55258945Sroberto#include "ipcp.h" 56258945Sroberto#include "filter.h" 57258945Sroberto#include "descriptor.h" 58258945Sroberto#include "lcp.h" 59258945Sroberto#include "ccp.h" 60258945Sroberto#include "link.h" 61258945Sroberto#include "mp.h" 62258945Sroberto#ifndef NORADIUS 63258945Sroberto#include "radius.h" 64258945Sroberto#endif 65258945Sroberto#include "ipv6cp.h" 66258945Sroberto#include "ncp.h" 67258945Sroberto#include "bundle.h" 68258945Sroberto#include "async.h" 69258945Sroberto#include "physical.h" 70258945Sroberto#include "proto.h" 71258945Sroberto 72258945Srobertostatic void FsmSendConfigReq(struct fsm *); 73258945Srobertostatic void FsmSendTerminateReq(struct fsm *); 74258945Srobertostatic void FsmInitRestartCounter(struct fsm *, int); 75258945Sroberto 76258945Srobertotypedef void (recvfn)(struct fsm *, struct fsmheader *, struct mbuf *); 77258945Srobertostatic recvfn FsmRecvConfigReq, FsmRecvConfigAck, FsmRecvConfigNak, 78258945Sroberto FsmRecvConfigRej, FsmRecvTermReq, FsmRecvTermAck, 79258945Sroberto FsmRecvCodeRej, FsmRecvProtoRej, FsmRecvEchoReq, 80258945Sroberto FsmRecvEchoRep, FsmRecvDiscReq, FsmRecvIdent, 81258945Sroberto FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck; 82258945Sroberto 83258945Srobertostatic const struct fsmcodedesc { 84258945Sroberto recvfn *recv; 85258945Sroberto unsigned check_reqid : 1; 86258945Sroberto unsigned inc_reqid : 1; 87258945Sroberto const char *name; 88258945Sroberto} FsmCodes[] = { 89258945Sroberto { FsmRecvConfigReq, 0, 0, "ConfigReq" }, 90258945Sroberto { FsmRecvConfigAck, 1, 1, "ConfigAck" }, 91258945Sroberto { FsmRecvConfigNak, 1, 1, "ConfigNak" }, 92258945Sroberto { FsmRecvConfigRej, 1, 1, "ConfigRej" }, 93258945Sroberto { FsmRecvTermReq, 0, 0, "TerminateReq" }, 94258945Sroberto { FsmRecvTermAck, 1, 1, "TerminateAck" }, 95258945Sroberto { FsmRecvCodeRej, 0, 0, "CodeRej" }, 96258945Sroberto { FsmRecvProtoRej, 0, 0, "ProtocolRej" }, 97258945Sroberto { FsmRecvEchoReq, 0, 0, "EchoRequest" }, 98258945Sroberto { FsmRecvEchoRep, 0, 0, "EchoReply" }, 99258945Sroberto { FsmRecvDiscReq, 0, 0, "DiscardReq" }, 100258945Sroberto { FsmRecvIdent, 0, 1, "Ident" }, 101258945Sroberto { FsmRecvTimeRemain,0, 0, "TimeRemain" }, 102280849Scy { FsmRecvResetReq, 0, 0, "ResetReq" }, 103258945Sroberto { FsmRecvResetAck, 0, 1, "ResetAck" } 104258945Sroberto}; 105258945Sroberto 106258945Srobertostatic const char * 107258945SrobertoCode2Nam(u_int code) 108258945Sroberto{ 109258945Sroberto if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0]) 110258945Sroberto return "Unknown"; 111258945Sroberto return FsmCodes[code-1].name; 112258945Sroberto} 113258945Sroberto 114258945Srobertoconst char * 115258945SrobertoState2Nam(u_int state) 116258945Sroberto{ 117258945Sroberto static const char * const StateNames[] = { 118258945Sroberto "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping", 119258945Sroberto "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened", 120258945Sroberto }; 121258945Sroberto 122258945Sroberto if (state >= sizeof StateNames / sizeof StateNames[0]) 123258945Sroberto return "unknown"; 124258945Sroberto return StateNames[state]; 125258945Sroberto} 126258945Sroberto 127258945Srobertostatic void 128258945SrobertoStoppedTimeout(void *v) 129258945Sroberto{ 130 struct fsm *fp = (struct fsm *)v; 131 132 log_Printf(fp->LogLevel, "%s: Stopped timer expired\n", fp->link->name); 133 if (fp->OpenTimer.state == TIMER_RUNNING) { 134 log_Printf(LogWARN, "%s: %s: aborting open delay due to stopped timer\n", 135 fp->link->name, fp->name); 136 timer_Stop(&fp->OpenTimer); 137 } 138 if (fp->state == ST_STOPPED) 139 fsm2initial(fp); 140} 141 142void 143fsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode, 144 int maxcode, int LogLevel, struct bundle *bundle, 145 struct link *l, const struct fsm_parent *parent, 146 struct fsm_callbacks *fn, const char * const timer_names[3]) 147{ 148 fp->name = name; 149 fp->proto = proto; 150 fp->min_code = mincode; 151 fp->max_code = maxcode; 152 fp->state = fp->min_code > CODE_TERMACK ? ST_OPENED : ST_INITIAL; 153 fp->reqid = 1; 154 fp->restart = 1; 155 fp->more.reqs = fp->more.naks = fp->more.rejs = 3; 156 memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer); 157 memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer); 158 memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer); 159 fp->LogLevel = LogLevel; 160 fp->link = l; 161 fp->bundle = bundle; 162 fp->parent = parent; 163 fp->fn = fn; 164 fp->FsmTimer.name = timer_names[0]; 165 fp->OpenTimer.name = timer_names[1]; 166 fp->StoppedTimer.name = timer_names[2]; 167} 168 169static void 170NewState(struct fsm *fp, int new) 171{ 172 log_Printf(fp->LogLevel, "%s: State change %s --> %s\n", 173 fp->link->name, State2Nam(fp->state), State2Nam(new)); 174 if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING) 175 timer_Stop(&fp->StoppedTimer); 176 fp->state = new; 177 if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) { 178 timer_Stop(&fp->FsmTimer); 179 if (new == ST_STOPPED && fp->StoppedTimer.load) { 180 timer_Stop(&fp->StoppedTimer); 181 fp->StoppedTimer.func = StoppedTimeout; 182 fp->StoppedTimer.arg = (void *) fp; 183 timer_Start(&fp->StoppedTimer); 184 } 185 } 186} 187 188void 189fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count, 190 int mtype) 191{ 192 int plen; 193 struct fsmheader lh; 194 struct mbuf *bp; 195 196 if (log_IsKept(fp->LogLevel)) { 197 log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n", 198 fp->link->name, Code2Nam(code), id, State2Nam(fp->state)); 199 switch (code) { 200 case CODE_CONFIGREQ: 201 case CODE_CONFIGACK: 202 case CODE_CONFIGREJ: 203 case CODE_CONFIGNAK: 204 (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL); 205 if (count < sizeof(struct fsmconfig)) 206 log_Printf(fp->LogLevel, " [EMPTY]\n"); 207 break; 208 } 209 } 210 211 plen = sizeof(struct fsmheader) + count; 212 lh.code = code; 213 lh.id = id; 214 lh.length = htons(plen); 215 bp = m_get(plen, mtype); 216 memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader)); 217 if (count) 218 memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count); 219 log_DumpBp(LogDEBUG, "fsm_Output", bp); 220 link_PushPacket(fp->link, bp, fp->bundle, LINK_QUEUES(fp->link) - 1, 221 fp->proto); 222 223 if (code == CODE_CONFIGREJ) 224 lcp_SendIdentification(&fp->link->lcp); 225} 226 227static void 228FsmOpenNow(void *v) 229{ 230 struct fsm *fp = (struct fsm *)v; 231 232 timer_Stop(&fp->OpenTimer); 233 if (fp->state <= ST_STOPPED) { 234 if (fp->state != ST_STARTING) { 235 /* 236 * In practice, we're only here in ST_STOPPED (when delaying the 237 * first config request) or ST_CLOSED (when openmode == 0). 238 * 239 * The ST_STOPPED bit is breaking the RFC already :-( 240 * 241 * According to the RFC (1661) state transition table, a TLS isn't 242 * required for an Open event when state == Closed, but the RFC 243 * must be wrong as TLS hasn't yet been called (since the last TLF) 244 * ie, Initial gets an `Up' event, Closing gets a RTA etc. 245 */ 246 (*fp->fn->LayerStart)(fp); 247 (*fp->parent->LayerStart)(fp->parent->object, fp); 248 } 249 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 250 FsmSendConfigReq(fp); 251 NewState(fp, ST_REQSENT); 252 } 253} 254 255void 256fsm_Open(struct fsm *fp) 257{ 258 switch (fp->state) { 259 case ST_INITIAL: 260 NewState(fp, ST_STARTING); 261 (*fp->fn->LayerStart)(fp); 262 (*fp->parent->LayerStart)(fp->parent->object, fp); 263 break; 264 case ST_CLOSED: 265 if (fp->open_mode == OPEN_PASSIVE) { 266 NewState(fp, ST_STOPPED); /* XXX: This is a hack ! */ 267 } else if (fp->open_mode > 0) { 268 if (fp->open_mode > 1) 269 log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n", 270 fp->link->name, fp->open_mode); 271 NewState(fp, ST_STOPPED); /* XXX: This is a not-so-bad hack ! */ 272 timer_Stop(&fp->OpenTimer); 273 fp->OpenTimer.load = fp->open_mode * SECTICKS; 274 fp->OpenTimer.func = FsmOpenNow; 275 fp->OpenTimer.arg = (void *)fp; 276 timer_Start(&fp->OpenTimer); 277 } else 278 FsmOpenNow(fp); 279 break; 280 case ST_STOPPED: /* XXX: restart option */ 281 case ST_REQSENT: 282 case ST_ACKRCVD: 283 case ST_ACKSENT: 284 case ST_OPENED: /* XXX: restart option */ 285 break; 286 case ST_CLOSING: /* XXX: restart option */ 287 case ST_STOPPING: /* XXX: restart option */ 288 NewState(fp, ST_STOPPING); 289 break; 290 } 291} 292 293void 294fsm_Up(struct fsm *fp) 295{ 296 switch (fp->state) { 297 case ST_INITIAL: 298 log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n", 299 fp->link->name); 300 NewState(fp, ST_CLOSED); 301 break; 302 case ST_STARTING: 303 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 304 FsmSendConfigReq(fp); 305 NewState(fp, ST_REQSENT); 306 break; 307 default: 308 log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n", 309 fp->link->name, State2Nam(fp->state)); 310 break; 311 } 312} 313 314void 315fsm_Down(struct fsm *fp) 316{ 317 switch (fp->state) { 318 case ST_CLOSED: 319 NewState(fp, ST_INITIAL); 320 break; 321 case ST_CLOSING: 322 /* This TLF contradicts the RFC (1661), which ``misses it out'' ! */ 323 (*fp->fn->LayerFinish)(fp); 324 NewState(fp, ST_INITIAL); 325 (*fp->parent->LayerFinish)(fp->parent->object, fp); 326 break; 327 case ST_STOPPED: 328 NewState(fp, ST_STARTING); 329 (*fp->fn->LayerStart)(fp); 330 (*fp->parent->LayerStart)(fp->parent->object, fp); 331 break; 332 case ST_STOPPING: 333 case ST_REQSENT: 334 case ST_ACKRCVD: 335 case ST_ACKSENT: 336 NewState(fp, ST_STARTING); 337 break; 338 case ST_OPENED: 339 (*fp->fn->LayerDown)(fp); 340 NewState(fp, ST_STARTING); 341 (*fp->parent->LayerDown)(fp->parent->object, fp); 342 break; 343 } 344} 345 346void 347fsm_Close(struct fsm *fp) 348{ 349 switch (fp->state) { 350 case ST_STARTING: 351 (*fp->fn->LayerFinish)(fp); 352 NewState(fp, ST_INITIAL); 353 (*fp->parent->LayerFinish)(fp->parent->object, fp); 354 break; 355 case ST_STOPPED: 356 NewState(fp, ST_CLOSED); 357 break; 358 case ST_STOPPING: 359 NewState(fp, ST_CLOSING); 360 break; 361 case ST_OPENED: 362 (*fp->fn->LayerDown)(fp); 363 if (fp->state == ST_OPENED) { 364 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 365 FsmSendTerminateReq(fp); 366 NewState(fp, ST_CLOSING); 367 (*fp->parent->LayerDown)(fp->parent->object, fp); 368 } 369 break; 370 case ST_REQSENT: 371 case ST_ACKRCVD: 372 case ST_ACKSENT: 373 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 374 FsmSendTerminateReq(fp); 375 NewState(fp, ST_CLOSING); 376 break; 377 } 378} 379 380/* 381 * Send functions 382 */ 383static void 384FsmSendConfigReq(struct fsm *fp) 385{ 386 if (fp->more.reqs-- > 0 && fp->restart-- > 0) { 387 (*fp->fn->SendConfigReq)(fp); 388 timer_Start(&fp->FsmTimer); /* Start restart timer */ 389 } else { 390 if (fp->more.reqs < 0) 391 log_Printf(LogPHASE, "%s: Too many %s REQs sent - abandoning " 392 "negotiation\n", fp->link->name, fp->name); 393 lcp_SendIdentification(&fp->link->lcp); 394 fsm_Close(fp); 395 } 396} 397 398static void 399FsmSendTerminateReq(struct fsm *fp) 400{ 401 fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0, MB_UNKNOWN); 402 (*fp->fn->SentTerminateReq)(fp); 403 timer_Start(&fp->FsmTimer); /* Start restart timer */ 404 fp->restart--; /* Decrement restart counter */ 405} 406 407/* 408 * Timeout actions 409 */ 410static void 411FsmTimeout(void *v) 412{ 413 struct fsm *fp = (struct fsm *)v; 414 415 if (fp->restart) { 416 switch (fp->state) { 417 case ST_CLOSING: 418 case ST_STOPPING: 419 FsmSendTerminateReq(fp); 420 break; 421 case ST_REQSENT: 422 case ST_ACKSENT: 423 FsmSendConfigReq(fp); 424 break; 425 case ST_ACKRCVD: 426 FsmSendConfigReq(fp); 427 NewState(fp, ST_REQSENT); 428 break; 429 } 430 timer_Start(&fp->FsmTimer); 431 } else { 432 switch (fp->state) { 433 case ST_CLOSING: 434 (*fp->fn->LayerFinish)(fp); 435 NewState(fp, ST_CLOSED); 436 (*fp->parent->LayerFinish)(fp->parent->object, fp); 437 break; 438 case ST_STOPPING: 439 (*fp->fn->LayerFinish)(fp); 440 NewState(fp, ST_STOPPED); 441 (*fp->parent->LayerFinish)(fp->parent->object, fp); 442 break; 443 case ST_REQSENT: /* XXX: 3p */ 444 case ST_ACKSENT: 445 case ST_ACKRCVD: 446 (*fp->fn->LayerFinish)(fp); 447 NewState(fp, ST_STOPPED); 448 (*fp->parent->LayerFinish)(fp->parent->object, fp); 449 break; 450 } 451 } 452} 453 454static void 455FsmInitRestartCounter(struct fsm *fp, int what) 456{ 457 timer_Stop(&fp->FsmTimer); 458 fp->FsmTimer.func = FsmTimeout; 459 fp->FsmTimer.arg = (void *)fp; 460 (*fp->fn->InitRestartCounter)(fp, what); 461} 462 463/* 464 * Actions when receive packets 465 */ 466static void 467FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 468/* RCR */ 469{ 470 struct fsm_decode dec; 471 int plen, flen; 472 int ackaction = 0; 473 474 plen = m_length(bp); 475 flen = ntohs(lhp->length) - sizeof *lhp; 476 if (plen < flen) { 477 log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n", 478 fp->link->name, plen, flen); 479 m_freem(bp); 480 return; 481 } 482 483 /* Check and process easy case */ 484 switch (fp->state) { 485 case ST_INITIAL: 486 if (fp->proto == PROTO_CCP && fp->link->lcp.fsm.state == ST_OPENED) { 487 /* 488 * ccp_SetOpenMode() leaves us in initial if we're disabling 489 * & denying everything. 490 */ 491 bp = m_prepend(bp, lhp, sizeof *lhp, 2); 492 bp = proto_Prepend(bp, fp->proto, 0, 0); 493 bp = m_pullup(bp); 494 lcp_SendProtoRej(&fp->link->lcp, MBUF_CTOP(bp), bp->m_len); 495 m_freem(bp); 496 return; 497 } 498 /* Drop through */ 499 case ST_STARTING: 500 log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n", 501 fp->link->name, State2Nam(fp->state)); 502 m_freem(bp); 503 return; 504 case ST_CLOSED: 505 (*fp->fn->SendTerminateAck)(fp, lhp->id); 506 m_freem(bp); 507 return; 508 case ST_CLOSING: 509 log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n", 510 fp->link->name, State2Nam(fp->state)); 511 case ST_STOPPING: 512 m_freem(bp); 513 return; 514 case ST_OPENED: 515 (*fp->fn->LayerDown)(fp); 516 break; 517 } 518 519 bp = m_pullup(bp); 520 dec.ackend = dec.ack; 521 dec.nakend = dec.nak; 522 dec.rejend = dec.rej; 523 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec); 524 if (flen < sizeof(struct fsmconfig)) 525 log_Printf(fp->LogLevel, " [EMPTY]\n"); 526 527 if (dec.nakend == dec.nak && dec.rejend == dec.rej) 528 ackaction = 1; 529 530 switch (fp->state) { 531 case ST_STOPPED: 532 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 533 /* Fall through */ 534 535 case ST_OPENED: 536 FsmSendConfigReq(fp); 537 break; 538 } 539 540 if (dec.rejend != dec.rej) 541 fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej, 542 MB_UNKNOWN); 543 if (dec.nakend != dec.nak) 544 fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak, 545 MB_UNKNOWN); 546 if (ackaction) 547 fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack, 548 MB_UNKNOWN); 549 550 switch (fp->state) { 551 case ST_STOPPED: 552 /* 553 * According to the RFC (1661) state transition table, a TLS isn't 554 * required for a RCR when state == ST_STOPPED, but the RFC 555 * must be wrong as TLS hasn't yet been called (since the last TLF) 556 */ 557 (*fp->fn->LayerStart)(fp); 558 (*fp->parent->LayerStart)(fp->parent->object, fp); 559 /* Fall through */ 560 561 case ST_OPENED: 562 if (ackaction) 563 NewState(fp, ST_ACKSENT); 564 else 565 NewState(fp, ST_REQSENT); 566 (*fp->parent->LayerDown)(fp->parent->object, fp); 567 break; 568 case ST_REQSENT: 569 if (ackaction) 570 NewState(fp, ST_ACKSENT); 571 break; 572 case ST_ACKRCVD: 573 if (ackaction) { 574 NewState(fp, ST_OPENED); 575 if ((*fp->fn->LayerUp)(fp)) 576 (*fp->parent->LayerUp)(fp->parent->object, fp); 577 else { 578 (*fp->fn->LayerDown)(fp); 579 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 580 FsmSendTerminateReq(fp); 581 NewState(fp, ST_CLOSING); 582 lcp_SendIdentification(&fp->link->lcp); 583 } 584 } 585 break; 586 case ST_ACKSENT: 587 if (!ackaction) 588 NewState(fp, ST_REQSENT); 589 break; 590 } 591 m_freem(bp); 592 593 if (dec.rejend != dec.rej && --fp->more.rejs <= 0) { 594 log_Printf(LogPHASE, "%s: Too many %s REJs sent - abandoning negotiation\n", 595 fp->link->name, fp->name); 596 lcp_SendIdentification(&fp->link->lcp); 597 fsm_Close(fp); 598 } 599 600 if (dec.nakend != dec.nak && --fp->more.naks <= 0) { 601 log_Printf(LogPHASE, "%s: Too many %s NAKs sent - abandoning negotiation\n", 602 fp->link->name, fp->name); 603 lcp_SendIdentification(&fp->link->lcp); 604 fsm_Close(fp); 605 } 606} 607 608static void 609FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 610/* RCA */ 611{ 612 switch (fp->state) { 613 case ST_CLOSED: 614 case ST_STOPPED: 615 (*fp->fn->SendTerminateAck)(fp, lhp->id); 616 break; 617 case ST_CLOSING: 618 case ST_STOPPING: 619 break; 620 case ST_REQSENT: 621 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 622 NewState(fp, ST_ACKRCVD); 623 break; 624 case ST_ACKRCVD: 625 FsmSendConfigReq(fp); 626 NewState(fp, ST_REQSENT); 627 break; 628 case ST_ACKSENT: 629 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 630 NewState(fp, ST_OPENED); 631 if ((*fp->fn->LayerUp)(fp)) 632 (*fp->parent->LayerUp)(fp->parent->object, fp); 633 else { 634 (*fp->fn->LayerDown)(fp); 635 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 636 FsmSendTerminateReq(fp); 637 NewState(fp, ST_CLOSING); 638 lcp_SendIdentification(&fp->link->lcp); 639 } 640 break; 641 case ST_OPENED: 642 (*fp->fn->LayerDown)(fp); 643 FsmSendConfigReq(fp); 644 NewState(fp, ST_REQSENT); 645 (*fp->parent->LayerDown)(fp->parent->object, fp); 646 break; 647 } 648 m_freem(bp); 649} 650 651static void 652FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 653/* RCN */ 654{ 655 struct fsm_decode dec; 656 int plen, flen; 657 658 plen = m_length(bp); 659 flen = ntohs(lhp->length) - sizeof *lhp; 660 if (plen < flen) { 661 m_freem(bp); 662 return; 663 } 664 665 /* 666 * Check and process easy case 667 */ 668 switch (fp->state) { 669 case ST_INITIAL: 670 case ST_STARTING: 671 log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n", 672 fp->link->name, State2Nam(fp->state)); 673 m_freem(bp); 674 return; 675 case ST_CLOSED: 676 case ST_STOPPED: 677 (*fp->fn->SendTerminateAck)(fp, lhp->id); 678 m_freem(bp); 679 return; 680 case ST_CLOSING: 681 case ST_STOPPING: 682 m_freem(bp); 683 return; 684 } 685 686 bp = m_pullup(bp); 687 dec.ackend = dec.ack; 688 dec.nakend = dec.nak; 689 dec.rejend = dec.rej; 690 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec); 691 if (flen < sizeof(struct fsmconfig)) 692 log_Printf(fp->LogLevel, " [EMPTY]\n"); 693 694 switch (fp->state) { 695 case ST_REQSENT: 696 case ST_ACKSENT: 697 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 698 FsmSendConfigReq(fp); 699 break; 700 case ST_OPENED: 701 (*fp->fn->LayerDown)(fp); 702 FsmSendConfigReq(fp); 703 NewState(fp, ST_REQSENT); 704 (*fp->parent->LayerDown)(fp->parent->object, fp); 705 break; 706 case ST_ACKRCVD: 707 FsmSendConfigReq(fp); 708 NewState(fp, ST_REQSENT); 709 break; 710 } 711 712 m_freem(bp); 713} 714 715static void 716FsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 717/* RTR */ 718{ 719 switch (fp->state) { 720 case ST_INITIAL: 721 case ST_STARTING: 722 log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n", 723 fp->link->name, State2Nam(fp->state)); 724 break; 725 case ST_CLOSED: 726 case ST_STOPPED: 727 case ST_CLOSING: 728 case ST_STOPPING: 729 case ST_REQSENT: 730 (*fp->fn->SendTerminateAck)(fp, lhp->id); 731 break; 732 case ST_ACKRCVD: 733 case ST_ACKSENT: 734 (*fp->fn->SendTerminateAck)(fp, lhp->id); 735 NewState(fp, ST_REQSENT); 736 break; 737 case ST_OPENED: 738 (*fp->fn->LayerDown)(fp); 739 (*fp->fn->SendTerminateAck)(fp, lhp->id); 740 FsmInitRestartCounter(fp, FSM_TRM_TIMER); 741 timer_Start(&fp->FsmTimer); /* Start restart timer */ 742 fp->restart = 0; 743 NewState(fp, ST_STOPPING); 744 (*fp->parent->LayerDown)(fp->parent->object, fp); 745 /* A delayed ST_STOPPED is now scheduled */ 746 break; 747 } 748 m_freem(bp); 749} 750 751static void 752FsmRecvTermAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 753/* RTA */ 754{ 755 switch (fp->state) { 756 case ST_CLOSING: 757 (*fp->fn->LayerFinish)(fp); 758 NewState(fp, ST_CLOSED); 759 (*fp->parent->LayerFinish)(fp->parent->object, fp); 760 break; 761 case ST_STOPPING: 762 (*fp->fn->LayerFinish)(fp); 763 NewState(fp, ST_STOPPED); 764 (*fp->parent->LayerFinish)(fp->parent->object, fp); 765 break; 766 case ST_ACKRCVD: 767 NewState(fp, ST_REQSENT); 768 break; 769 case ST_OPENED: 770 (*fp->fn->LayerDown)(fp); 771 FsmSendConfigReq(fp); 772 NewState(fp, ST_REQSENT); 773 (*fp->parent->LayerDown)(fp->parent->object, fp); 774 break; 775 } 776 m_freem(bp); 777} 778 779static void 780FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 781/* RCJ */ 782{ 783 struct fsm_decode dec; 784 int plen, flen; 785 786 plen = m_length(bp); 787 flen = ntohs(lhp->length) - sizeof *lhp; 788 if (plen < flen) { 789 m_freem(bp); 790 return; 791 } 792 793 lcp_SendIdentification(&fp->link->lcp); 794 795 /* 796 * Check and process easy case 797 */ 798 switch (fp->state) { 799 case ST_INITIAL: 800 case ST_STARTING: 801 log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n", 802 fp->link->name, State2Nam(fp->state)); 803 m_freem(bp); 804 return; 805 case ST_CLOSED: 806 case ST_STOPPED: 807 (*fp->fn->SendTerminateAck)(fp, lhp->id); 808 m_freem(bp); 809 return; 810 case ST_CLOSING: 811 case ST_STOPPING: 812 m_freem(bp); 813 return; 814 } 815 816 bp = m_pullup(bp); 817 dec.ackend = dec.ack; 818 dec.nakend = dec.nak; 819 dec.rejend = dec.rej; 820 (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec); 821 if (flen < sizeof(struct fsmconfig)) 822 log_Printf(fp->LogLevel, " [EMPTY]\n"); 823 824 switch (fp->state) { 825 case ST_REQSENT: 826 case ST_ACKSENT: 827 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 828 FsmSendConfigReq(fp); 829 break; 830 case ST_OPENED: 831 (*fp->fn->LayerDown)(fp); 832 FsmSendConfigReq(fp); 833 NewState(fp, ST_REQSENT); 834 (*fp->parent->LayerDown)(fp->parent->object, fp); 835 break; 836 case ST_ACKRCVD: 837 FsmSendConfigReq(fp); 838 NewState(fp, ST_REQSENT); 839 break; 840 } 841 m_freem(bp); 842} 843 844static void 845FsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 846{ 847 m_freem(bp); 848} 849 850static void 851FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 852{ 853 struct physical *p = link2physical(fp->link); 854 u_short proto; 855 856 if (m_length(bp) < 2) { 857 m_freem(bp); 858 return; 859 } 860 bp = mbuf_Read(bp, &proto, 2); 861 proto = ntohs(proto); 862 log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n", 863 fp->link->name, proto, hdlc_Protocol2Nam(proto)); 864 865 switch (proto) { 866 case PROTO_LQR: 867 if (p) 868 lqr_Stop(p, LQM_LQR); 869 else 870 log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n", 871 fp->link->name); 872 break; 873 case PROTO_CCP: 874 if (fp->proto == PROTO_LCP) { 875 fp = &fp->link->ccp.fsm; 876 /* Despite the RFC (1661), don't do an out-of-place TLF */ 877 /* (*fp->fn->LayerFinish)(fp); */ 878 switch (fp->state) { 879 case ST_CLOSED: 880 case ST_CLOSING: 881 NewState(fp, ST_CLOSED); 882 break; 883 default: 884 NewState(fp, ST_STOPPED); 885 break; 886 } 887 /* See above */ 888 /* (*fp->parent->LayerFinish)(fp->parent->object, fp); */ 889 } 890 break; 891 case PROTO_IPCP: 892 if (fp->proto == PROTO_LCP) { 893 log_Printf(LogPHASE, "%s: IPCP protocol reject closes IPCP !\n", 894 fp->link->name); 895 fsm_Close(&fp->bundle->ncp.ipcp.fsm); 896 } 897 break; 898#ifndef NOINET6 899 case PROTO_IPV6CP: 900 if (fp->proto == PROTO_LCP) { 901 log_Printf(LogPHASE, "%s: IPV6CP protocol reject closes IPV6CP !\n", 902 fp->link->name); 903 fsm_Close(&fp->bundle->ncp.ipv6cp.fsm); 904 } 905 break; 906#endif 907 case PROTO_MP: 908 if (fp->proto == PROTO_LCP) { 909 struct lcp *lcp = fsm2lcp(fp); 910 911 if (lcp->want_mrru && lcp->his_mrru) { 912 log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n", 913 fp->link->name); 914 fsm_Close(fp); 915 } 916 } 917 break; 918 } 919 m_freem(bp); 920} 921 922static void 923FsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 924{ 925 struct lcp *lcp = fsm2lcp(fp); 926 u_char *cp; 927 u_int32_t magic; 928 929 bp = m_pullup(bp); 930 m_settype(bp, MB_ECHOIN); 931 932 if (lcp && ntohs(lhp->length) - sizeof *lhp >= 4) { 933 cp = MBUF_CTOP(bp); 934 ua_ntohl(cp, &magic); 935 if (magic != lcp->his_magic) { 936 log_Printf(fp->LogLevel, "%s: RecvEchoReq: magic 0x%08lx is wrong," 937 " expecting 0x%08lx\n", fp->link->name, (u_long)magic, 938 (u_long)lcp->his_magic); 939 /* XXX: We should send terminate request */ 940 } 941 if (fp->state == ST_OPENED) { 942 ua_htonl(&lcp->want_magic, cp); /* local magic */ 943 fsm_Output(fp, CODE_ECHOREP, lhp->id, cp, 944 ntohs(lhp->length) - sizeof *lhp, MB_ECHOOUT); 945 } 946 } 947 m_freem(bp); 948} 949 950static void 951FsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 952{ 953 if (fsm2lcp(fp)) 954 bp = lqr_RecvEcho(fp, bp); 955 956 m_freem(bp); 957} 958 959static void 960FsmRecvDiscReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 961{ 962 m_freem(bp); 963} 964 965static void 966FsmRecvIdent(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 967{ 968 u_int32_t magic; 969 u_short len; 970 u_char *cp; 971 972 len = ntohs(lhp->length) - sizeof *lhp; 973 if (len >= 4) { 974 bp = m_pullup(m_append(bp, "", 1)); 975 cp = MBUF_CTOP(bp); 976 ua_ntohl(cp, &magic); 977 if (magic != fp->link->lcp.his_magic) 978 log_Printf(fp->LogLevel, "%s: RecvIdent: magic 0x%08lx is wrong," 979 " expecting 0x%08lx\n", fp->link->name, (u_long)magic, 980 (u_long)fp->link->lcp.his_magic); 981 cp[len] = '\0'; 982 lcp_RecvIdentification(&fp->link->lcp, cp + 4); 983 } 984 m_freem(bp); 985} 986 987static void 988FsmRecvTimeRemain(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 989{ 990 m_freem(bp); 991} 992 993static void 994FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 995{ 996 if ((*fp->fn->RecvResetReq)(fp)) { 997 /* 998 * All sendable compressed packets are queued in the first (lowest 999 * priority) modem output queue.... dump 'em to the priority queue 1000 * so that they arrive at the peer before our ResetAck. 1001 */ 1002 link_SequenceQueue(fp->link); 1003 fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0, MB_CCPOUT); 1004 } 1005 m_freem(bp); 1006} 1007 1008static void 1009FsmRecvResetAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) 1010{ 1011 (*fp->fn->RecvResetAck)(fp, lhp->id); 1012 m_freem(bp); 1013} 1014 1015void 1016fsm_Input(struct fsm *fp, struct mbuf *bp) 1017{ 1018 int len; 1019 struct fsmheader lh; 1020 const struct fsmcodedesc *codep; 1021 1022 len = m_length(bp); 1023 if (len < sizeof(struct fsmheader)) { 1024 m_freem(bp); 1025 return; 1026 } 1027 bp = mbuf_Read(bp, &lh, sizeof lh); 1028 1029 if (ntohs(lh.length) > len) { 1030 log_Printf(LogWARN, "%s: Oops: Got %d bytes but %d byte payload " 1031 "- dropped\n", fp->link->name, len, (int)ntohs(lh.length)); 1032 m_freem(bp); 1033 return; 1034 } 1035 1036 if (lh.code < fp->min_code || lh.code > fp->max_code || 1037 lh.code > sizeof FsmCodes / sizeof *FsmCodes) { 1038 /* 1039 * Use a private id. This is really a response-type packet, but we 1040 * MUST send a unique id for each REQ.... 1041 */ 1042 static u_char id; 1043 1044 bp = m_prepend(bp, &lh, sizeof lh, 0); 1045 bp = m_pullup(bp); 1046 fsm_Output(fp, CODE_CODEREJ, id++, MBUF_CTOP(bp), bp->m_len, MB_UNKNOWN); 1047 m_freem(bp); 1048 return; 1049 } 1050 1051 codep = FsmCodes + lh.code - 1; 1052 if (lh.id != fp->reqid && codep->check_reqid && 1053 Enabled(fp->bundle, OPT_IDCHECK)) { 1054 log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n", 1055 fp->link->name, codep->name, lh.id, fp->reqid); 1056 return; 1057 } 1058 1059 log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n", 1060 fp->link->name, codep->name, lh.id, State2Nam(fp->state)); 1061 1062 if (codep->inc_reqid && (lh.id == fp->reqid || 1063 (!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid))) 1064 fp->reqid++; /* That's the end of that ``exchange''.... */ 1065 1066 (*codep->recv)(fp, &lh, bp); 1067} 1068 1069int 1070fsm_NullRecvResetReq(struct fsm *fp) 1071{ 1072 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n", 1073 fp->link->name); 1074 return 1; 1075} 1076 1077void 1078fsm_NullRecvResetAck(struct fsm *fp, u_char id) 1079{ 1080 log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset ack\n", 1081 fp->link->name); 1082} 1083 1084void 1085fsm_Reopen(struct fsm *fp) 1086{ 1087 if (fp->state == ST_OPENED) { 1088 (*fp->fn->LayerDown)(fp); 1089 FsmInitRestartCounter(fp, FSM_REQ_TIMER); 1090 FsmSendConfigReq(fp); 1091 NewState(fp, ST_REQSENT); 1092 (*fp->parent->LayerDown)(fp->parent->object, fp); 1093 } 1094} 1095 1096void 1097fsm2initial(struct fsm *fp) 1098{ 1099 timer_Stop(&fp->FsmTimer); 1100 timer_Stop(&fp->OpenTimer); 1101 timer_Stop(&fp->StoppedTimer); 1102 if (fp->state == ST_STOPPED) 1103 fsm_Close(fp); 1104 if (fp->state > ST_INITIAL) 1105 fsm_Down(fp); 1106 if (fp->state > ST_INITIAL) 1107 fsm_Close(fp); 1108} 1109