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