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