1 /* 2 * PPP Link Control Protocol (LCP) Module 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:$ 21 * 22 * TODO: 23 * o Validate magic number received from peer. 24 * o Limit data field length by MRU 25 */ 26 #if __FreeBSD__ >=2 27 #include <sys/time.h> 28 #endif 29 #include "fsm.h" 30 #include "lcp.h" 31 #include "ipcp.h" 32 #include "lcpproto.h" 33 #include "os.h" 34 #include "hdlc.h" 35 #include "lqr.h" 36 #include "phase.h" 37 #include "vars.h" 38 39 extern void IpcpUp(); 40 extern void IpcpOpen(); 41 extern void SendPapChallenge(); 42 extern void SendChapChallenge(); 43 extern void SetLinkParams(struct lcpstate *); 44 extern void Prompt(); 45 extern void StopIdleTimer(); 46 extern void HdlcInit(); 47 extern void OsLinkdown(); 48 extern void Cleanup(); 49 50 struct lcpstate LcpInfo; 51 52 static void LcpSendConfigReq(struct fsm *); 53 static void LcpSendTerminateReq(struct fsm *fp); 54 static void LcpSendTerminateAck(struct fsm *fp); 55 static void LcpDecodeConfig(struct mbuf *bp, int mode); 56 static void LcpInitRestartCounter(struct fsm *); 57 static void LcpLayerUp(struct fsm *); 58 static void LcpLayerDown(struct fsm *); 59 static void LcpLayerStart(struct fsm *); 60 static void LcpLayerFinish(struct fsm *); 61 62 extern int ModemSpeed(); 63 64 #define REJECTED(p, x) (p->his_reject & (1<<x)) 65 66 static char *cftypes[] = { 67 "???", "MRU", "ACCMAP", "AUTHPROTO", "QUALPROTO", "MAGICNUM", 68 "RESERVED", "PROTOCOMP", "ACFCOMP", "FCSALT", "SDP", 69 }; 70 71 struct fsm LcpFsm = { 72 "LCP", /* Name of protocol */ 73 PROTO_LCP, /* Protocol Number */ 74 LCP_MAXCODE, 75 OPEN_ACTIVE, 76 ST_INITIAL, /* State of machine */ 77 0, 0, 0, 78 79 0, 80 { 0, 0, 0, NULL, NULL, NULL }, 81 82 LcpLayerUp, 83 LcpLayerDown, 84 LcpLayerStart, 85 LcpLayerFinish, 86 LcpInitRestartCounter, 87 LcpSendConfigReq, 88 LcpSendTerminateReq, 89 LcpSendTerminateAck, 90 LcpDecodeConfig, 91 }; 92 93 static struct pppTimer LcpReportTimer; 94 95 char *PhaseNames[] = { 96 "Dead", "Establish", "Authenticate", "Network", "Terminate" 97 }; 98 99 void 100 NewPhase(new) 101 int new; 102 { 103 struct lcpstate *lcp = &LcpInfo; 104 105 phase = new; 106 LogPrintf(LOG_PHASE, "Phase: %s\n", PhaseNames[phase]); 107 switch (phase) { 108 case PHASE_AUTHENTICATE: 109 lcp->auth_ineed = lcp->want_auth; 110 lcp->auth_iwait = lcp->his_auth; 111 LogPrintf(LOG_PHASE, " his = %x, mine = %x\n", lcp->his_auth, lcp->want_auth); 112 if (lcp->his_auth || lcp->want_auth) { 113 if (lcp->his_auth == PROTO_PAP) 114 SendPapChallenge(); 115 if (lcp->want_auth == PROTO_CHAP) 116 SendChapChallenge(); 117 } else 118 NewPhase(PHASE_NETWORK); 119 break; 120 case PHASE_NETWORK: 121 IpcpUp(); 122 IpcpOpen(); 123 CcpUp(); 124 CcpOpen(); 125 break; 126 case PHASE_DEAD: 127 if (mode & MODE_DIRECT) 128 Cleanup(EX_DEAD); 129 break; 130 } 131 } 132 133 static void 134 LcpReportTime() 135 { 136 #ifdef VERBOSE 137 time_t t; 138 139 time(&t); 140 logprintf("%s", ctime(&t)); 141 #endif 142 StopTimer(&LcpReportTimer); 143 LcpReportTimer.state = TIMER_STOPPED; 144 StartTimer(&LcpReportTimer); 145 HdlcErrorCheck(); 146 } 147 148 int 149 ReportLcpStatus() 150 { 151 struct lcpstate *lcp = &LcpInfo; 152 struct fsm *fp = &LcpFsm; 153 154 printf("%s [%s]\n", fp->name, StateNames[fp->state]); 155 printf( 156 " his side: MRU %d, ACCMAP %08x, PROTOCOMP %d, ACFCOMP %d MAGIC %08x\n", 157 lcp->his_mru, lcp->his_accmap, lcp->his_protocomp, lcp->his_acfcomp, lcp->his_magic); 158 printf( 159 " my side: MRU %d, ACCMAP %08x, PROTOCOMP %d, ACFCOMP %d MAGIC %08x\n", 160 lcp->want_mru, lcp->want_accmap, lcp->want_protocomp, lcp->want_acfcomp, lcp->want_magic); 161 printf("\nDefaults: MRU = %d, ACCMAP = %08x\t", VarMRU, VarAccmap); 162 printf("Open Mode: %s\n", (VarOpenMode == OPEN_ACTIVE)? "active" : "passive"); 163 return(1); 164 } 165 166 /* 167 * Generate random number which will be used as magic number. 168 */ 169 u_long 170 GenerateMagic() 171 { 172 time_t tl; 173 struct timeval tval; 174 175 time(&tl); 176 gettimeofday(&tval, NULL); 177 tl += tval.tv_sec ^ tval.tv_usec + getppid(); 178 tl *= getpid(); 179 return(tl); 180 } 181 182 void 183 LcpInit() 184 { 185 struct lcpstate *lcp = &LcpInfo; 186 187 FsmInit(&LcpFsm); 188 HdlcInit(); 189 190 bzero(lcp, sizeof(struct lcpstate)); 191 lcp->want_mru = VarMRU; 192 lcp->his_mru = DEF_MRU; 193 lcp->his_accmap = 0xffffffff; 194 lcp->want_accmap = VarAccmap; 195 lcp->want_magic = GenerateMagic(); 196 lcp->want_auth = lcp->his_auth = 0; 197 if (Enabled(ConfChap)) 198 lcp->want_auth = PROTO_CHAP; 199 else if (Enabled(ConfPap)) 200 lcp->want_auth = PROTO_PAP; 201 if (Enabled(ConfLqr)) lcp->want_lqrperiod = VarLqrTimeout * 100; 202 if (Enabled(ConfAcfcomp)) lcp->want_acfcomp = 1; 203 if (Enabled(ConfProtocomp)) lcp->want_protocomp = 1; 204 LcpFsm.maxconfig = 10; 205 } 206 207 static void 208 LcpInitRestartCounter(fp) 209 struct fsm *fp; 210 { 211 fp->FsmTimer.load = 5 * SECTICKS; 212 fp->restart = 5; 213 } 214 215 void 216 PutConfValue(cpp, types, type, len, val) 217 u_char **cpp; 218 char **types; 219 u_char type; 220 int len; 221 u_long val; 222 { 223 u_char *cp; 224 225 cp = *cpp; 226 *cp++ = type; *cp++ = len; 227 if (len == 6) { 228 if (type == TY_IPADDR) { 229 LogPrintf(LOG_LCP, " %s [%d] %s\n", 230 types[type], len, inet_ntoa(htonl(val))); 231 } else { 232 LogPrintf(LOG_LCP, " %s [%d] %08x\n", types[type], len, val); 233 } 234 *cp++ = (val >> 24) & 0377; 235 *cp++ = (val >> 16) & 0377; 236 } else 237 LogPrintf(LOG_LCP, " %s [%d] %d\n", types[type], len, val); 238 *cp++ = (val >> 8) & 0377; 239 *cp++ = val & 0377; 240 *cpp = cp; 241 } 242 243 static void 244 LcpSendConfigReq(fp) 245 struct fsm *fp; 246 { 247 u_char *cp; 248 struct lcpstate *lcp = &LcpInfo; 249 struct lqrreq *req; 250 251 LogPrintf(LOG_LCP, "%s: SendConfigReq\n", fp->name); 252 cp = ReqBuff; 253 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP)) { 254 *cp++ = TY_ACFCOMP; *cp++ = 2; 255 LogPrintf(LOG_LCP, " %s\n", cftypes[TY_ACFCOMP]); 256 } 257 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP)) { 258 *cp++ = TY_PROTOCOMP; *cp++ = 2; 259 LogPrintf(LOG_LCP, " %s\n", cftypes[TY_PROTOCOMP]); 260 } 261 if (!REJECTED(lcp, TY_MRU)) 262 PutConfValue(&cp, cftypes, TY_MRU, 4, lcp->want_mru); 263 if (!REJECTED(lcp, TY_ACCMAP)) 264 PutConfValue(&cp, cftypes, TY_ACCMAP, 6, lcp->want_accmap); 265 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) 266 PutConfValue(&cp, cftypes, TY_MAGICNUM, 6, lcp->want_magic); 267 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) { 268 req = (struct lqrreq *)cp; 269 req->type = TY_QUALPROTO; req->length = sizeof(struct lqrreq); 270 req->proto = htons(PROTO_LQR); 271 req->period = htonl(lcp->want_lqrperiod); 272 cp += sizeof(struct lqrreq); 273 LogPrintf(LOG_LCP, " %s (%d)\n", cftypes[TY_QUALPROTO], lcp->want_lqrperiod); 274 } 275 switch (lcp->want_auth) { 276 case PROTO_PAP: 277 PutConfValue(&cp, cftypes, TY_AUTHPROTO, 4, lcp->want_auth); 278 break; 279 case PROTO_CHAP: 280 PutConfValue(&cp, cftypes, TY_AUTHPROTO, 5, lcp->want_auth); 281 *cp++ = 5; /* Use MD5 */ 282 break; 283 } 284 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 285 } 286 287 void 288 LcpSendProtoRej(option, count) 289 u_char *option; 290 int count; 291 { 292 struct fsm *fp = &LcpFsm; 293 294 LogPrintf(LOG_LCP, "%s: SendProtoRej\n", fp->name); 295 FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count); 296 } 297 298 static void 299 LcpSendTerminateReq(fp) 300 struct fsm *fp; 301 { 302 /* Most thins are done in fsm layer. Nothing to to. */ 303 } 304 305 static void 306 LcpSendTerminateAck(fp) 307 struct fsm *fp; 308 { 309 LogPrintf(LOG_LCP, "%s: SendTerminateAck.\n", fp->name); 310 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 311 } 312 313 static void 314 LcpLayerStart(fp) 315 struct fsm *fp; 316 { 317 LogPrintf(LOG_LCP, "%s: LayerStart\n", fp->name); 318 NewPhase(PHASE_ESTABLISH); 319 } 320 321 static void 322 LcpLayerFinish(fp) 323 struct fsm *fp; 324 { 325 #ifdef VERBOSE 326 fprintf(stderr, "%s: LayerFinish\r\n", fp->name); 327 #endif 328 Prompt(1); 329 LogPrintf(LOG_LCP, "%s: LayerFinish\n", fp->name); 330 #ifdef notdef 331 OsCloseLink(0); 332 #else 333 OsCloseLink(1); 334 #endif 335 NewPhase(PHASE_DEAD); 336 StopTimer(&LcpReportTimer); 337 StopIdleTimer(); 338 OsInterfaceDown(0); 339 } 340 341 static void 342 LcpLayerUp(fp) 343 struct fsm *fp; 344 { 345 LogPrintf(LOG_LCP, "%s: LayerUp\n", fp->name); 346 OsSetInterfaceParams(23, LcpInfo.his_mru, ModemSpeed()); 347 SetLinkParams(&LcpInfo); 348 349 NewPhase(PHASE_AUTHENTICATE); 350 351 StartLqm(); 352 StopTimer(&LcpReportTimer); 353 LcpReportTimer.state = TIMER_STOPPED; 354 LcpReportTimer.load = 60 * SECTICKS; 355 LcpReportTimer.func = LcpReportTime; 356 StartTimer(&LcpReportTimer); 357 } 358 359 static void 360 LcpLayerDown(fp) 361 struct fsm *fp; 362 { 363 LogPrintf(LOG_LCP, "%s: LayerDown\n", fp->name); 364 OsLinkdown(); 365 NewPhase(PHASE_TERMINATE); 366 } 367 368 void 369 LcpUp() 370 { 371 FsmUp(&LcpFsm); 372 } 373 374 void 375 LcpDown() 376 { 377 NewPhase(PHASE_DEAD); 378 FsmDown(&LcpFsm); 379 } 380 381 void 382 LcpOpen(mode) 383 int mode; 384 { 385 LcpFsm.open_mode = mode; 386 FsmOpen(&LcpFsm); 387 } 388 389 void 390 LcpClose() 391 { 392 FsmClose(&LcpFsm); 393 } 394 395 /* 396 * XXX: Should validate option length 397 */ 398 static void 399 LcpDecodeConfig(bp, mode) 400 struct mbuf *bp; 401 int mode; 402 { 403 u_char *cp; 404 char *request; 405 int plen, type, length, mru; 406 u_long *lp, magic, accmap; 407 u_short *sp, proto; 408 struct lqrreq *req; 409 410 plen = plength(bp); 411 412 cp = MBUF_CTOP(bp); 413 ackp = AckBuff; 414 nakp = NakBuff; 415 rejp = RejBuff; 416 417 while (plen >= sizeof(struct fsmconfig)) { 418 type = *cp; 419 length = cp[1]; 420 if (type <= TY_ACFCOMP) 421 request = cftypes[type]; 422 else 423 request = "???"; 424 425 switch (type) { 426 case TY_MRU: 427 sp = (u_short *)(cp + 2); 428 mru = htons(*sp); 429 LogPrintf(LOG_LCP, " %s %d\n", request, mru); 430 431 switch (mode) { 432 case MODE_REQ: 433 if (mru > MAX_MRU) { 434 *sp = htons(MAX_MRU); 435 bcopy(cp, nakp, 4); nakp += 4; 436 } else if (mru < MIN_MRU) { 437 *sp = htons(MIN_MRU); 438 bcopy(cp, nakp, 4); nakp += 4; 439 } else { 440 LcpInfo.his_mru = mru; 441 bcopy(cp, ackp, 4); ackp += 4; 442 } 443 break; 444 case MODE_NAK: 445 if (mru >= MIN_MRU || mru <= MAX_MRU) 446 LcpInfo.want_mru = mru; 447 break; 448 case MODE_REJ: 449 LcpInfo.his_reject |= (1 << type); 450 break; 451 } 452 break; 453 case TY_ACCMAP: 454 lp = (u_long *)(cp + 2); 455 accmap = htonl(*lp); 456 LogPrintf(LOG_LCP, " %s %08x\n", request, accmap); 457 458 switch (mode) { 459 case MODE_REQ: 460 LcpInfo.his_accmap = accmap; 461 bcopy(cp, ackp, 6); ackp += 6; 462 break; 463 case MODE_NAK: 464 LcpInfo.want_accmap = accmap; 465 break; 466 case MODE_REJ: 467 LcpInfo.his_reject |= (1 << type); 468 break; 469 } 470 break; 471 case TY_AUTHPROTO: 472 sp = (u_short *)(cp + 2); 473 proto = ntohs(*sp); 474 LogPrintf(LOG_LCP, " %s proto = %x\n", request, proto); 475 476 switch (mode) { 477 case MODE_REQ: 478 switch (proto) { 479 case PROTO_PAP: 480 if (length != 4) { 481 LogPrintf(LOG_LCP, " %s bad length (%d)\n", request, length); 482 goto reqreject; 483 } 484 if (Acceptable(ConfPap)) { 485 LcpInfo.his_auth = proto; 486 bcopy(cp, ackp, length); ackp += length; 487 } else if (Acceptable(ConfChap)) { 488 *nakp++ = *cp; *nakp++ = 5; 489 *nakp++ = (unsigned char)PROTO_CHAP >> 8; 490 *nakp++ = (unsigned char)PROTO_CHAP; 491 *nakp++ = 5; 492 } else 493 goto reqreject; 494 break; 495 case PROTO_CHAP: 496 if (length < 5) { 497 LogPrintf(LOG_LCP, " %s bad length (%d)\n", request, length); 498 goto reqreject; 499 } 500 if (Acceptable(ConfChap) && cp[4] == 5) { 501 LcpInfo.his_auth = proto; 502 bcopy(cp, ackp, length); ackp += length; 503 } else if (Acceptable(ConfPap)) { 504 *nakp++ = *cp; *nakp++ = 4; 505 *nakp++ = (unsigned char)PROTO_PAP >> 8; 506 *nakp++ = (unsigned char)PROTO_PAP; 507 } else 508 goto reqreject; 509 break; 510 default: 511 LogPrintf(LOG_LCP, " %s not implemented.\n", request); 512 goto reqreject; 513 } 514 break; 515 case MODE_NAK: 516 break; 517 case MODE_REJ: 518 LcpInfo.his_reject |= (1 << type); 519 break; 520 } 521 break; 522 case TY_QUALPROTO: 523 req = (struct lqrreq *)cp; 524 LogPrintf(LOG_LCP, " %s proto: %x, interval: %dms\n", 525 request, ntohs(req->proto), ntohl(req->period)*10); 526 switch (mode) { 527 case MODE_REQ: 528 if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr)) 529 goto reqreject; 530 else { 531 LcpInfo.his_lqrperiod = ntohl(req->period); 532 if (LcpInfo.his_lqrperiod < 500) 533 LcpInfo.his_lqrperiod = 500; 534 req->period = htonl(LcpInfo.his_lqrperiod); 535 bcopy(cp, ackp, length); ackp += length; 536 } 537 break; 538 case MODE_NAK: 539 break; 540 case MODE_REJ: 541 LcpInfo.his_reject |= (1 << type); 542 break; 543 } 544 break; 545 case TY_MAGICNUM: 546 lp = (u_long *)(cp + 2); 547 magic = ntohl(*lp); 548 LogPrintf(LOG_LCP, " %s %08x\n", request, magic); 549 550 switch (mode) { 551 case MODE_REQ: 552 if (LcpInfo.want_magic) { 553 /* XXX: Shoud validate magic number */ 554 if (magic == LcpInfo.want_magic) 555 logprintf("magic is same!! %x, %x, %x\n", 556 magic, LcpInfo.want_magic, LcpInfo.his_magic); 557 LcpInfo.his_magic = magic; 558 bcopy(cp, ackp, length); ackp += length; 559 } else { 560 LcpInfo.my_reject |= (1 << type); 561 goto reqreject; 562 } 563 break; 564 case MODE_NAK: 565 LogPrintf(LOG_LCP, " %s magic %08x has NAKed\n", request, magic); 566 LcpInfo.want_magic = GenerateMagic(); 567 break; 568 case MODE_REJ: 569 LogPrintf(LOG_LCP, " %s magic has REJected\n", request); 570 LcpInfo.want_magic = 0; 571 LcpInfo.his_reject |= (1 << type); 572 break; 573 } 574 break; 575 case TY_PROTOCOMP: 576 LogPrintf(LOG_LCP, " %s\n", request); 577 578 switch (mode) { 579 case MODE_REQ: 580 if (Acceptable(ConfProtocomp)) { 581 LcpInfo.his_protocomp = 1; 582 bcopy(cp, ackp, 2); ackp += 2; 583 } else { 584 #ifdef OLDMST 585 /* 586 * MorningStar before v1.3 needs NAK 587 */ 588 bcopy(cp, nakp, 2); nakp += 2; 589 #else 590 bcopy(cp, rejp, 2); rejp += 2; 591 LcpInfo.my_reject |= (1 << type); 592 #endif 593 } 594 break; 595 case MODE_NAK: 596 case MODE_REJ: 597 LcpInfo.want_protocomp = 0; 598 LcpInfo.his_reject |= (1 << type); 599 break; 600 } 601 break; 602 case TY_ACFCOMP: 603 LogPrintf(LOG_LCP, " %s\n", request); 604 switch (mode) { 605 case MODE_REQ: 606 if (Acceptable(ConfAcfcomp)) { 607 LcpInfo.his_acfcomp = 1; 608 bcopy(cp, ackp, 2); 609 ackp += 2; 610 } else { 611 #ifdef OLDMST 612 /* 613 * MorningStar before v1.3 needs NAK 614 */ 615 bcopy(cp, nakp, 2); 616 nakp += 2; 617 #else 618 bcopy(cp, rejp, 2); 619 rejp += 2; 620 LcpInfo.my_reject |= (1 << type); 621 #endif 622 } 623 break; 624 case MODE_NAK: 625 case MODE_REJ: 626 LcpInfo.want_acfcomp = 0; 627 LcpInfo.his_reject |= (1 << type); 628 break; 629 } 630 break; 631 case TY_SDP: 632 LogPrintf(LOG_LCP, " %s\n", request); 633 switch (mode) { 634 case MODE_REQ: 635 case MODE_NAK: 636 case MODE_REJ: 637 break; 638 } 639 break; 640 default: 641 reqreject: 642 bcopy(cp, rejp, length); 643 rejp += length; 644 LcpInfo.my_reject |= (1 << type); 645 break; 646 } 647 plen -= length; 648 cp += length; 649 } 650 } 651 652 void 653 LcpInput(struct mbuf *bp) 654 { 655 FsmInput(&LcpFsm, bp); 656 } 657