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: lcp.c,v 1.8 1996/01/30 11:08:35 dfr Exp $ 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 } 383 384 void 385 LcpUp() 386 { 387 FsmUp(&LcpFsm); 388 } 389 390 void 391 LcpDown() /* Sudden death */ 392 { 393 NewPhase(PHASE_DEAD); 394 StopAllTimers(); 395 FsmDown(&LcpFsm); 396 } 397 398 void 399 LcpOpen(mode) 400 int mode; 401 { 402 LcpFsm.open_mode = mode; 403 FsmOpen(&LcpFsm); 404 } 405 406 void 407 LcpClose() 408 { 409 FsmClose(&LcpFsm); 410 } 411 412 /* 413 * XXX: Should validate option length 414 */ 415 static void 416 LcpDecodeConfig(cp, plen, mode) 417 u_char *cp; 418 int plen; 419 int mode; 420 { 421 char *request; 422 int type, length, mru; 423 u_long *lp, magic, accmap; 424 u_short *sp, proto; 425 struct lqrreq *req; 426 427 ackp = AckBuff; 428 nakp = NakBuff; 429 rejp = RejBuff; 430 431 while (plen >= sizeof(struct fsmconfig)) { 432 type = *cp; 433 length = cp[1]; 434 if (type <= TY_ACFCOMP) 435 request = cftypes[type]; 436 else 437 request = "???"; 438 439 switch (type) { 440 case TY_MRU: 441 sp = (u_short *)(cp + 2); 442 mru = htons(*sp); 443 LogPrintf(LOG_LCP_BIT, " %s %d\n", request, mru); 444 445 switch (mode) { 446 case MODE_REQ: 447 if (mru > MAX_MRU) { 448 *sp = htons(MAX_MRU); 449 bcopy(cp, nakp, 4); nakp += 4; 450 } else if (mru < MIN_MRU) { 451 *sp = htons(MIN_MRU); 452 bcopy(cp, nakp, 4); nakp += 4; 453 } else { 454 LcpInfo.his_mru = mru; 455 bcopy(cp, ackp, 4); ackp += 4; 456 } 457 break; 458 case MODE_NAK: 459 if (mru >= MIN_MRU || mru <= MAX_MRU) 460 LcpInfo.want_mru = mru; 461 break; 462 case MODE_REJ: 463 LcpInfo.his_reject |= (1 << type); 464 break; 465 } 466 break; 467 case TY_ACCMAP: 468 lp = (u_long *)(cp + 2); 469 accmap = htonl(*lp); 470 LogPrintf(LOG_LCP_BIT, " %s %08x\n", request, accmap); 471 472 switch (mode) { 473 case MODE_REQ: 474 LcpInfo.his_accmap = accmap; 475 bcopy(cp, ackp, 6); ackp += 6; 476 break; 477 case MODE_NAK: 478 LcpInfo.want_accmap = accmap; 479 break; 480 case MODE_REJ: 481 LcpInfo.his_reject |= (1 << type); 482 break; 483 } 484 break; 485 case TY_AUTHPROTO: 486 sp = (u_short *)(cp + 2); 487 proto = ntohs(*sp); 488 LogPrintf(LOG_LCP_BIT, " %s proto = %04x\n", request, proto); 489 490 switch (mode) { 491 case MODE_REQ: 492 switch (proto) { 493 case PROTO_PAP: 494 if (length != 4) { 495 LogPrintf(LOG_LCP_BIT, " %s bad length (%d)\n", request, length); 496 goto reqreject; 497 } 498 if (Acceptable(ConfPap)) { 499 LcpInfo.his_auth = proto; 500 bcopy(cp, ackp, length); ackp += length; 501 } else if (Acceptable(ConfChap)) { 502 *nakp++ = *cp; *nakp++ = 5; 503 *nakp++ = (unsigned char)(PROTO_CHAP >> 8); 504 *nakp++ = (unsigned char)PROTO_CHAP; 505 *nakp++ = 5; 506 } else 507 goto reqreject; 508 break; 509 case PROTO_CHAP: 510 if (length < 5) { 511 LogPrintf(LOG_LCP_BIT, " %s bad length (%d)\n", request, length); 512 goto reqreject; 513 } 514 if (Acceptable(ConfChap) && cp[4] == 5) { 515 LcpInfo.his_auth = proto; 516 bcopy(cp, ackp, length); ackp += length; 517 } else if (Acceptable(ConfPap)) { 518 *nakp++ = *cp; *nakp++ = 4; 519 *nakp++ = (unsigned char)(PROTO_PAP >> 8); 520 *nakp++ = (unsigned char)PROTO_PAP; 521 } else 522 goto reqreject; 523 break; 524 default: 525 LogPrintf(LOG_LCP_BIT, " %s not implemented, NAK.\n", request); 526 bcopy(cp, nakp, length); 527 nakp += length; 528 break; 529 } 530 break; 531 case MODE_NAK: 532 break; 533 case MODE_REJ: 534 LcpInfo.his_reject |= (1 << type); 535 break; 536 } 537 break; 538 case TY_QUALPROTO: 539 req = (struct lqrreq *)cp; 540 LogPrintf(LOG_LCP_BIT, " %s proto: %x, interval: %dms\n", 541 request, ntohs(req->proto), ntohl(req->period)*10); 542 switch (mode) { 543 case MODE_REQ: 544 if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr)) 545 goto reqreject; 546 else { 547 LcpInfo.his_lqrperiod = ntohl(req->period); 548 if (LcpInfo.his_lqrperiod < 500) 549 LcpInfo.his_lqrperiod = 500; 550 req->period = htonl(LcpInfo.his_lqrperiod); 551 bcopy(cp, ackp, length); ackp += length; 552 } 553 break; 554 case MODE_NAK: 555 break; 556 case MODE_REJ: 557 LcpInfo.his_reject |= (1 << type); 558 break; 559 } 560 break; 561 case TY_MAGICNUM: 562 lp = (u_long *)(cp + 2); 563 magic = ntohl(*lp); 564 LogPrintf(LOG_LCP_BIT, " %s %08x\n", request, magic); 565 566 switch (mode) { 567 case MODE_REQ: 568 if (LcpInfo.want_magic) { 569 /* XXX: Shoud validate magic number */ 570 if (magic == LcpInfo.want_magic) 571 logprintf("magic is same!! %x, %x, %x\n", 572 magic, LcpInfo.want_magic, LcpInfo.his_magic); 573 LcpInfo.his_magic = magic; 574 bcopy(cp, ackp, length); ackp += length; 575 } else { 576 LcpInfo.my_reject |= (1 << type); 577 goto reqreject; 578 } 579 break; 580 case MODE_NAK: 581 LogPrintf(LOG_LCP_BIT, " %s magic %08x has NAKed\n", request, magic); 582 LcpInfo.want_magic = GenerateMagic(); 583 break; 584 case MODE_REJ: 585 LogPrintf(LOG_LCP_BIT, " %s magic has REJected\n", request); 586 LcpInfo.want_magic = 0; 587 LcpInfo.his_reject |= (1 << type); 588 break; 589 } 590 break; 591 case TY_PROTOCOMP: 592 LogPrintf(LOG_LCP_BIT, " %s\n", request); 593 594 switch (mode) { 595 case MODE_REQ: 596 if (Acceptable(ConfProtocomp)) { 597 LcpInfo.his_protocomp = 1; 598 bcopy(cp, ackp, 2); ackp += 2; 599 } else { 600 #ifdef OLDMST 601 /* 602 * MorningStar before v1.3 needs NAK 603 */ 604 bcopy(cp, nakp, 2); nakp += 2; 605 #else 606 bcopy(cp, rejp, 2); rejp += 2; 607 LcpInfo.my_reject |= (1 << type); 608 #endif 609 } 610 break; 611 case MODE_NAK: 612 case MODE_REJ: 613 LcpInfo.want_protocomp = 0; 614 LcpInfo.his_reject |= (1 << type); 615 break; 616 } 617 break; 618 case TY_ACFCOMP: 619 LogPrintf(LOG_LCP_BIT, " %s\n", request); 620 switch (mode) { 621 case MODE_REQ: 622 if (Acceptable(ConfAcfcomp)) { 623 LcpInfo.his_acfcomp = 1; 624 bcopy(cp, ackp, 2); 625 ackp += 2; 626 } else { 627 #ifdef OLDMST 628 /* 629 * MorningStar before v1.3 needs NAK 630 */ 631 bcopy(cp, nakp, 2); 632 nakp += 2; 633 #else 634 bcopy(cp, rejp, 2); 635 rejp += 2; 636 LcpInfo.my_reject |= (1 << type); 637 #endif 638 } 639 break; 640 case MODE_NAK: 641 case MODE_REJ: 642 LcpInfo.want_acfcomp = 0; 643 LcpInfo.his_reject |= (1 << type); 644 break; 645 } 646 break; 647 case TY_SDP: 648 LogPrintf(LOG_LCP_BIT, " %s\n", request); 649 switch (mode) { 650 case MODE_REQ: 651 case MODE_NAK: 652 case MODE_REJ: 653 break; 654 } 655 break; 656 default: 657 LogPrintf(LOG_LCP_BIT, " ???[%02x]\n", type); 658 if (mode == MODE_REQ) { 659 reqreject: 660 bcopy(cp, rejp, length); 661 rejp += length; 662 LcpInfo.my_reject |= (1 << type); 663 } 664 break; 665 } 666 plen -= length; 667 cp += length; 668 } 669 } 670 671 void 672 LcpInput(struct mbuf *bp) 673 { 674 FsmInput(&LcpFsm, bp); 675 } 676