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.63 1998/09/04 18:25:59 brian Exp $ 21 * 22 * TODO: 23 * o Limit data field length by MRU 24 */ 25 26 #include <sys/types.h> 27 #include <netinet/in.h> 28 #include <netinet/in_systm.h> 29 #include <netinet/ip.h> 30 #include <sys/un.h> 31 32 #include <signal.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <termios.h> 37 #include <unistd.h> 38 39 #include "ua.h" 40 #include "defs.h" 41 #include "command.h" 42 #include "mbuf.h" 43 #include "log.h" 44 #include "timer.h" 45 #include "fsm.h" 46 #include "iplist.h" 47 #include "lcp.h" 48 #include "throughput.h" 49 #include "lcpproto.h" 50 #include "descriptor.h" 51 #include "lqr.h" 52 #include "hdlc.h" 53 #include "ccp.h" 54 #include "async.h" 55 #include "link.h" 56 #include "physical.h" 57 #include "prompt.h" 58 #include "slcompress.h" 59 #include "ipcp.h" 60 #include "filter.h" 61 #include "mp.h" 62 #include "chat.h" 63 #include "auth.h" 64 #include "chap.h" 65 #include "cbcp.h" 66 #include "datalink.h" 67 #include "bundle.h" 68 69 /* for received LQRs */ 70 struct lqrreq { 71 u_char type; 72 u_char length; 73 u_short proto; /* Quality protocol */ 74 u_int32_t period; /* Reporting interval */ 75 }; 76 77 static int LcpLayerUp(struct fsm *); 78 static void LcpLayerDown(struct fsm *); 79 static void LcpLayerStart(struct fsm *); 80 static void LcpLayerFinish(struct fsm *); 81 static void LcpInitRestartCounter(struct fsm *); 82 static void LcpSendConfigReq(struct fsm *); 83 static void LcpSentTerminateReq(struct fsm *); 84 static void LcpSendTerminateAck(struct fsm *, u_char); 85 static void LcpDecodeConfig(struct fsm *, u_char *, int, int, 86 struct fsm_decode *); 87 88 static struct fsm_callbacks lcp_Callbacks = { 89 LcpLayerUp, 90 LcpLayerDown, 91 LcpLayerStart, 92 LcpLayerFinish, 93 LcpInitRestartCounter, 94 LcpSendConfigReq, 95 LcpSentTerminateReq, 96 LcpSendTerminateAck, 97 LcpDecodeConfig, 98 fsm_NullRecvResetReq, 99 fsm_NullRecvResetAck 100 }; 101 102 static const char *lcp_TimerNames[] = 103 {"LCP restart", "LCP openmode", "LCP stopped"}; 104 105 static const char *cftypes[] = { 106 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 107 "???", 108 "MRU", /* 1: Maximum-Receive-Unit */ 109 "ACCMAP", /* 2: Async-Control-Character-Map */ 110 "AUTHPROTO", /* 3: Authentication-Protocol */ 111 "QUALPROTO", /* 4: Quality-Protocol */ 112 "MAGICNUM", /* 5: Magic-Number */ 113 "RESERVED", /* 6: RESERVED */ 114 "PROTOCOMP", /* 7: Protocol-Field-Compression */ 115 "ACFCOMP", /* 8: Address-and-Control-Field-Compression */ 116 "FCSALT", /* 9: FCS-Alternatives */ 117 "SDP", /* 10: Self-Describing-Pad */ 118 "NUMMODE", /* 11: Numbered-Mode */ 119 "MULTIPROC", /* 12: Multi-Link-Procedure */ 120 "CALLBACK", /* 13: Callback */ 121 "CONTIME", /* 14: Connect-Time */ 122 "COMPFRAME", /* 15: Compound-Frames */ 123 "NDE", /* 16: Nominal-Data-Encapsulation */ 124 "MRRU", /* 17: Multilink-MRRU */ 125 "SHORTSEQ", /* 18: Multilink-Short-Sequence-Number-Header */ 126 "ENDDISC", /* 19: Multilink-Endpoint-Discriminator */ 127 "PROPRIETRY", /* 20: Proprietary */ 128 "DCEID", /* 21: DCE-Identifier */ 129 "MULTIPP", /* 22: Multi-Link-Plus-Procedure */ 130 "LDBACP", /* 23: Link Discriminator for BACP */ 131 }; 132 133 #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 134 135 int 136 lcp_ReportStatus(struct cmdargs const *arg) 137 { 138 struct link *l; 139 struct lcp *lcp; 140 141 l = command_ChooseLink(arg); 142 lcp = &l->lcp; 143 144 prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name, 145 State2Nam(lcp->fsm.state)); 146 prompt_Printf(arg->prompt, 147 " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n" 148 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n", 149 lcp->his_mru, (u_long)lcp->his_accmap, 150 lcp->his_protocomp ? "on" : "off", 151 lcp->his_acfcomp ? "on" : "off", 152 (u_long)lcp->his_magic, lcp->his_mrru, 153 lcp->his_shortseq ? "on" : "off", lcp->his_reject); 154 prompt_Printf(arg->prompt, 155 " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n" 156 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n", 157 lcp->want_mru, (u_long)lcp->want_accmap, 158 lcp->want_protocomp ? "on" : "off", 159 lcp->want_acfcomp ? "on" : "off", 160 (u_long)lcp->want_magic, lcp->want_mrru, 161 lcp->want_shortseq ? "on" : "off", lcp->my_reject); 162 163 prompt_Printf(arg->prompt, "\n Defaults: MRU = %d, ", lcp->cfg.mru); 164 prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap); 165 prompt_Printf(arg->prompt, " LQR period = %us, ", 166 lcp->cfg.lqrperiod); 167 prompt_Printf(arg->prompt, "Open Mode = %s", 168 lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active"); 169 if (lcp->cfg.openmode > 0) 170 prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode); 171 prompt_Printf(arg->prompt, "\n FSM retry = %us\n", 172 lcp->cfg.fsmretry); 173 prompt_Printf(arg->prompt, "\n Negotiation:\n"); 174 prompt_Printf(arg->prompt, " ACFCOMP = %s\n", 175 command_ShowNegval(lcp->cfg.acfcomp)); 176 prompt_Printf(arg->prompt, " CHAP = %s\n", 177 command_ShowNegval(lcp->cfg.chap)); 178 prompt_Printf(arg->prompt, " LQR = %s\n", 179 command_ShowNegval(lcp->cfg.lqr)); 180 prompt_Printf(arg->prompt, " PAP = %s\n", 181 command_ShowNegval(lcp->cfg.pap)); 182 prompt_Printf(arg->prompt, " PROTOCOMP = %s\n", 183 command_ShowNegval(lcp->cfg.protocomp)); 184 185 return 0; 186 } 187 188 static u_int32_t 189 GenerateMagic(void) 190 { 191 /* Generate random number which will be used as magic number */ 192 randinit(); 193 return random(); 194 } 195 196 void 197 lcp_SetupCallbacks(struct lcp *lcp) 198 { 199 lcp->fsm.fn = &lcp_Callbacks; 200 lcp->fsm.FsmTimer.name = lcp_TimerNames[0]; 201 lcp->fsm.OpenTimer.name = lcp_TimerNames[1]; 202 lcp->fsm.StoppedTimer.name = lcp_TimerNames[2]; 203 } 204 205 void 206 lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l, 207 const struct fsm_parent *parent) 208 { 209 /* Initialise ourselves */ 210 int mincode = parent ? 1 : LCP_MINMPCODE; 211 212 fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, 10, LogLCP, 213 bundle, l, parent, &lcp_Callbacks, lcp_TimerNames); 214 215 lcp->cfg.mru = DEF_MRU; 216 lcp->cfg.accmap = 0; 217 lcp->cfg.openmode = 1; 218 lcp->cfg.lqrperiod = DEF_LQRPERIOD; 219 lcp->cfg.fsmretry = DEF_FSMRETRY; 220 221 lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED; 222 lcp->cfg.chap = NEG_ACCEPTED; 223 lcp->cfg.lqr = NEG_ACCEPTED; 224 lcp->cfg.pap = NEG_ACCEPTED; 225 lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED; 226 227 lcp_Setup(lcp, lcp->cfg.openmode); 228 } 229 230 void 231 lcp_Setup(struct lcp *lcp, int openmode) 232 { 233 lcp->fsm.open_mode = openmode; 234 lcp->fsm.maxconfig = 10; 235 236 lcp->his_mru = lcp->fsm.bundle->cfg.mtu; 237 if (!lcp->his_mru || lcp->his_mru > DEF_MRU) 238 lcp->his_mru = DEF_MRU; 239 lcp->his_mrru = 0; 240 lcp->his_magic = 0; 241 lcp->his_lqrperiod = 0; 242 lcp->his_acfcomp = 0; 243 lcp->his_auth = 0; 244 lcp->his_callback.opmask = 0; 245 lcp->his_shortseq = 0; 246 247 lcp->want_mru = lcp->cfg.mru; 248 lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru; 249 lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0; 250 lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0; 251 252 if (lcp->fsm.parent) { 253 struct physical *p = link2physical(lcp->fsm.link); 254 255 lcp->his_accmap = 0xffffffff; 256 lcp->want_accmap = lcp->cfg.accmap; 257 lcp->his_protocomp = 0; 258 lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0; 259 lcp->want_magic = GenerateMagic(); 260 lcp->want_auth = IsEnabled(lcp->cfg.chap) ? PROTO_CHAP : 261 IsEnabled(lcp->cfg.pap) ? PROTO_PAP : 0; 262 if (p->type != PHYS_DIRECT) 263 memcpy(&lcp->want_callback, &p->dl->cfg.callback, sizeof(struct callback)); 264 else 265 lcp->want_callback.opmask = 0; 266 lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ? 267 lcp->cfg.lqrperiod * 100 : 0; 268 } else { 269 lcp->his_accmap = lcp->want_accmap = 0; 270 lcp->his_protocomp = lcp->want_protocomp = 1; 271 lcp->want_magic = 0; 272 lcp->want_auth = 0; 273 lcp->want_callback.opmask = 0; 274 lcp->want_lqrperiod = 0; 275 } 276 277 lcp->his_reject = lcp->my_reject = 0; 278 lcp->auth_iwait = lcp->auth_ineed = 0; 279 lcp->LcpFailedMagic = 0; 280 } 281 282 static void 283 LcpInitRestartCounter(struct fsm * fp) 284 { 285 /* Set fsm timer load */ 286 struct lcp *lcp = fsm2lcp(fp); 287 288 fp->FsmTimer.load = lcp->cfg.fsmretry * SECTICKS; 289 fp->restart = DEF_REQs; 290 } 291 292 static void 293 LcpSendConfigReq(struct fsm *fp) 294 { 295 /* Send config REQ please */ 296 struct physical *p = link2physical(fp->link); 297 struct lcp *lcp = fsm2lcp(fp); 298 u_char buff[200]; 299 struct lcp_opt *o; 300 struct mp *mp; 301 u_int16_t proto; 302 303 if (!p) { 304 log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n", 305 fp->link->name); 306 return; 307 } 308 309 o = (struct lcp_opt *)buff; 310 if (!physical_IsSync(p)) { 311 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP)) 312 INC_LCP_OPT(TY_ACFCOMP, 2, o); 313 314 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP)) 315 INC_LCP_OPT(TY_PROTOCOMP, 2, o); 316 317 if (!REJECTED(lcp, TY_ACCMAP)) { 318 ua_htonl(&lcp->want_accmap, o->data); 319 INC_LCP_OPT(TY_ACCMAP, 6, o); 320 } 321 } 322 323 if (!REJECTED(lcp, TY_MRU)) { 324 ua_htons(&lcp->want_mru, o->data); 325 INC_LCP_OPT(TY_MRU, 4, o); 326 } 327 328 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) { 329 ua_htonl(&lcp->want_magic, o->data); 330 INC_LCP_OPT(TY_MAGICNUM, 6, o); 331 } 332 333 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) { 334 proto = PROTO_LQR; 335 ua_htons(&proto, o->data); 336 ua_htonl(&lcp->want_lqrperiod, o->data + 2); 337 INC_LCP_OPT(TY_QUALPROTO, 8, o); 338 } 339 340 switch (lcp->want_auth) { 341 case PROTO_PAP: 342 proto = PROTO_PAP; 343 ua_htons(&proto, o->data); 344 INC_LCP_OPT(TY_AUTHPROTO, 4, o); 345 break; 346 347 case PROTO_CHAP: 348 proto = PROTO_CHAP; 349 ua_htons(&proto, o->data); 350 o->data[2] = 0x05; 351 INC_LCP_OPT(TY_AUTHPROTO, 5, o); 352 break; 353 } 354 355 if (!REJECTED(lcp, TY_CALLBACK)) { 356 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) { 357 *o->data = CALLBACK_AUTH; 358 INC_LCP_OPT(TY_CALLBACK, 3, o); 359 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) { 360 *o->data = CALLBACK_CBCP; 361 INC_LCP_OPT(TY_CALLBACK, 3, o); 362 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) { 363 int sz = strlen(lcp->want_callback.msg); 364 365 if (sz > sizeof o->data - 1) { 366 sz = sizeof o->data - 1; 367 log_Printf(LogWARN, "Truncating E164 data to %d octets (oops!)\n", sz); 368 } 369 *o->data = CALLBACK_E164; 370 memcpy(o->data + 1, lcp->want_callback.msg, sz); 371 INC_LCP_OPT(TY_CALLBACK, sz + 3, o); 372 } 373 } 374 375 if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) { 376 ua_htons(&lcp->want_mrru, o->data); 377 INC_LCP_OPT(TY_MRRU, 4, o); 378 379 if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ)) 380 INC_LCP_OPT(TY_SHORTSEQ, 2, o); 381 } 382 383 mp = &lcp->fsm.bundle->ncp.mp; 384 if (mp->cfg.enddisc.class != 0 && !REJECTED(lcp, TY_ENDDISC)) { 385 *o->data = mp->cfg.enddisc.class; 386 memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len); 387 INC_LCP_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o); 388 } 389 390 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 391 } 392 393 void 394 lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count) 395 { 396 /* Don't understand `option' */ 397 fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count); 398 } 399 400 static void 401 LcpSentTerminateReq(struct fsm * fp) 402 { 403 /* Term REQ just sent by FSM */ 404 } 405 406 static void 407 LcpSendTerminateAck(struct fsm *fp, u_char id) 408 { 409 /* Send Term ACK please */ 410 struct physical *p = link2physical(fp->link); 411 412 if (p && p->dl->state == DATALINK_CBCP) 413 cbcp_ReceiveTerminateReq(p); 414 415 fsm_Output(fp, CODE_TERMACK, id, NULL, 0); 416 } 417 418 static void 419 LcpLayerStart(struct fsm *fp) 420 { 421 /* We're about to start up ! */ 422 struct lcp *lcp = fsm2lcp(fp); 423 424 log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name); 425 lcp->LcpFailedMagic = 0; 426 } 427 428 static void 429 LcpLayerFinish(struct fsm *fp) 430 { 431 /* We're now down */ 432 log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name); 433 } 434 435 static int 436 LcpLayerUp(struct fsm *fp) 437 { 438 /* We're now up */ 439 struct physical *p = link2physical(fp->link); 440 struct lcp *lcp = fsm2lcp(fp); 441 442 log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name); 443 async_SetLinkParams(&p->async, lcp); 444 lqr_Start(lcp); 445 hdlc_StartTimer(&p->hdlc); 446 return 1; 447 } 448 449 static void 450 LcpLayerDown(struct fsm *fp) 451 { 452 /* About to come down */ 453 struct physical *p = link2physical(fp->link); 454 455 log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name); 456 hdlc_StopTimer(&p->hdlc); 457 lqr_StopTimer(p); 458 lcp_Setup(fsm2lcp(fp), 0); 459 } 460 461 static int 462 E164ok(struct callback *cb, char *req, int sz) 463 { 464 char list[sizeof cb->msg], *next; 465 int len; 466 467 if (!strcmp(cb->msg, "*")) 468 return 1; 469 470 strncpy(list, cb->msg, sizeof list - 1); 471 list[sizeof list - 1] = '\0'; 472 for (next = strtok(list, ","); next; next = strtok(NULL, ",")) { 473 len = strlen(next); 474 if (sz == len && !memcmp(list, req, sz)) 475 return 1; 476 } 477 return 0; 478 } 479 480 static void 481 LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 482 struct fsm_decode *dec) 483 { 484 /* Deal with incoming PROTO_LCP */ 485 struct lcp *lcp = fsm2lcp(fp); 486 int type, length, sz, pos, op, callback_req; 487 u_int32_t magic, accmap; 488 u_short mtu, mru, proto; 489 struct lqrreq *req; 490 char request[20], desc[22]; 491 struct mp *mp; 492 struct physical *p = link2physical(fp->link); 493 494 callback_req = 0; 495 496 while (plen >= sizeof(struct fsmconfig)) { 497 type = *cp; 498 length = cp[1]; 499 500 if (type < 0 || type >= NCFTYPES) 501 snprintf(request, sizeof request, " <%d>[%d]", type, length); 502 else 503 snprintf(request, sizeof request, " %s[%d]", cftypes[type], length); 504 505 if (length < 2) { 506 log_Printf(LogLCP, "%s:%s: Bad LCP length\n", fp->link->name, request); 507 break; 508 } 509 510 switch (type) { 511 case TY_MRRU: 512 mp = &lcp->fsm.bundle->ncp.mp; 513 ua_ntohs(cp + 2, &mru); 514 log_Printf(LogLCP, "%s %u\n", request, mru); 515 516 switch (mode_type) { 517 case MODE_REQ: 518 if (mp->cfg.mrru) { 519 if (REJECTED(lcp, TY_MRRU)) 520 /* Ignore his previous reject so that we REQ next time */ 521 lcp->his_reject &= ~(1 << type); 522 523 mtu = lcp->fsm.bundle->cfg.mtu; 524 if (mru < MIN_MRU || mru < mtu) { 525 /* Push him up to MTU or MIN_MRU */ 526 lcp->his_mrru = mru < mtu ? mtu : MIN_MRU; 527 memcpy(dec->nakend, cp, 2); 528 ua_htons(&lcp->his_mrru, dec->nakend + 2); 529 dec->nakend += 4; 530 } else { 531 lcp->his_mrru = mtu ? mtu : mru; 532 memcpy(dec->ackend, cp, 4); 533 dec->ackend += 4; 534 } 535 break; 536 } else 537 goto reqreject; 538 break; 539 case MODE_NAK: 540 if (mp->cfg.mrru) { 541 if (REJECTED(lcp, TY_MRRU)) 542 /* Must have changed his mind ! */ 543 lcp->his_reject &= ~(1 << type); 544 545 if (mru > MAX_MRU) 546 lcp->want_mrru = MAX_MRU; 547 else if (mru < MIN_MRU) 548 lcp->want_mrru = MIN_MRU; 549 else 550 lcp->want_mrru = mru; 551 } 552 /* else we honour our config and don't send the suggested REQ */ 553 break; 554 case MODE_REJ: 555 lcp->his_reject |= (1 << type); 556 lcp->want_mrru = 0; /* Ah well, no multilink :-( */ 557 break; 558 } 559 break; 560 561 case TY_MRU: 562 ua_ntohs(cp + 2, &mru); 563 log_Printf(LogLCP, "%s %d\n", request, mru); 564 565 switch (mode_type) { 566 case MODE_REQ: 567 mtu = lcp->fsm.bundle->cfg.mtu; 568 if (mru < MIN_MRU || (!lcp->want_mrru && mru < mtu)) { 569 /* Push him up to MTU or MIN_MRU */ 570 lcp->his_mru = mru < mtu ? mtu : MIN_MRU; 571 memcpy(dec->nakend, cp, 2); 572 ua_htons(&lcp->his_mru, dec->nakend + 2); 573 dec->nakend += 4; 574 } else { 575 lcp->his_mru = mtu ? mtu : mru; 576 memcpy(dec->ackend, cp, 4); 577 dec->ackend += 4; 578 } 579 break; 580 case MODE_NAK: 581 if (mru > MAX_MRU) 582 lcp->want_mru = MAX_MRU; 583 else if (mru < MIN_MRU) 584 lcp->want_mru = MIN_MRU; 585 else 586 lcp->want_mru = mru; 587 break; 588 case MODE_REJ: 589 lcp->his_reject |= (1 << type); 590 break; 591 } 592 break; 593 594 case TY_ACCMAP: 595 ua_ntohl(cp + 2, &accmap); 596 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap); 597 598 switch (mode_type) { 599 case MODE_REQ: 600 lcp->his_accmap = accmap; 601 memcpy(dec->ackend, cp, 6); 602 dec->ackend += 6; 603 break; 604 case MODE_NAK: 605 lcp->want_accmap = accmap; 606 break; 607 case MODE_REJ: 608 lcp->his_reject |= (1 << type); 609 break; 610 } 611 break; 612 613 case TY_AUTHPROTO: 614 ua_ntohs(cp + 2, &proto); 615 switch (proto) { 616 case PROTO_PAP: 617 log_Printf(LogLCP, "%s 0x%04x (PAP)\n", request, proto); 618 break; 619 case PROTO_CHAP: 620 log_Printf(LogLCP, "%s 0x%04x (CHAP 0x%02x)\n", request, proto, cp[4]); 621 break; 622 default: 623 log_Printf(LogLCP, "%s 0x%04x\n", request, proto); 624 break; 625 } 626 627 switch (mode_type) { 628 case MODE_REQ: 629 switch (proto) { 630 case PROTO_PAP: 631 if (length != 4) { 632 log_Printf(LogLCP, " Bad length!\n"); 633 goto reqreject; 634 } 635 if (IsAccepted(lcp->cfg.pap)) { 636 lcp->his_auth = proto; 637 memcpy(dec->ackend, cp, length); 638 dec->ackend += length; 639 } else if (IsAccepted(lcp->cfg.chap)) { 640 *dec->nakend++ = *cp; 641 *dec->nakend++ = 5; 642 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8); 643 *dec->nakend++ = (unsigned char) PROTO_CHAP; 644 *dec->nakend++ = 0x05; 645 } else 646 goto reqreject; 647 break; 648 649 case PROTO_CHAP: 650 if (length < 5) { 651 log_Printf(LogLCP, " Bad length!\n"); 652 goto reqreject; 653 } 654 #ifdef HAVE_DES 655 if (IsAccepted(lcp->cfg.chap) && (cp[4] == 0x05 || cp[4] == 0x80)) 656 #else 657 if (IsAccepted(lcp->cfg.chap) && cp[4] == 0x05) 658 #endif 659 { 660 lcp->his_auth = proto; 661 memcpy(dec->ackend, cp, length); 662 dec->ackend += length; 663 #ifdef HAVE_DES 664 link2physical(fp->link)->dl->chap.using_MSChap = cp[4] == 0x80; 665 #endif 666 } else if (IsAccepted(lcp->cfg.pap)) { 667 *dec->nakend++ = *cp; 668 *dec->nakend++ = 4; 669 *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8); 670 *dec->nakend++ = (unsigned char) PROTO_PAP; 671 } else 672 goto reqreject; 673 break; 674 675 default: 676 log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n", 677 request, proto); 678 memcpy(dec->nakend, cp, length); 679 dec->nakend += length; 680 break; 681 } 682 break; 683 case MODE_NAK: 684 switch (proto) { 685 case PROTO_PAP: 686 if (IsEnabled(lcp->cfg.pap)) 687 lcp->want_auth = PROTO_PAP; 688 else { 689 log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n"); 690 lcp->his_reject |= (1 << type); 691 } 692 break; 693 case PROTO_CHAP: 694 if (IsEnabled(lcp->cfg.chap)) 695 lcp->want_auth = PROTO_CHAP; 696 else { 697 log_Printf(LogLCP, "Peer will only send CHAP (not enabled)\n"); 698 lcp->his_reject |= (1 << type); 699 } 700 break; 701 default: 702 /* We've been NAK'd with something we don't understand :-( */ 703 lcp->his_reject |= (1 << type); 704 break; 705 } 706 break; 707 case MODE_REJ: 708 lcp->his_reject |= (1 << type); 709 break; 710 } 711 break; 712 713 case TY_QUALPROTO: 714 req = (struct lqrreq *)cp; 715 log_Printf(LogLCP, "%s proto %x, interval %lums\n", 716 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10); 717 switch (mode_type) { 718 case MODE_REQ: 719 if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr)) 720 goto reqreject; 721 else { 722 lcp->his_lqrperiod = ntohl(req->period); 723 if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100) 724 lcp->his_lqrperiod = MIN_LQRPERIOD * 100; 725 req->period = htonl(lcp->his_lqrperiod); 726 memcpy(dec->ackend, cp, length); 727 dec->ackend += length; 728 } 729 break; 730 case MODE_NAK: 731 break; 732 case MODE_REJ: 733 lcp->his_reject |= (1 << type); 734 break; 735 } 736 break; 737 738 case TY_MAGICNUM: 739 ua_ntohl(cp + 2, &magic); 740 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic); 741 742 switch (mode_type) { 743 case MODE_REQ: 744 if (lcp->want_magic) { 745 /* Validate magic number */ 746 if (magic == lcp->want_magic) { 747 log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n", 748 (u_long)magic, ++lcp->LcpFailedMagic); 749 lcp->want_magic = GenerateMagic(); 750 memcpy(dec->nakend, cp, 6); 751 dec->nakend += 6; 752 ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0); 753 sigpause(0); 754 } else { 755 lcp->his_magic = magic; 756 memcpy(dec->ackend, cp, length); 757 dec->ackend += length; 758 lcp->LcpFailedMagic = 0; 759 } 760 } else { 761 goto reqreject; 762 } 763 break; 764 case MODE_NAK: 765 log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic); 766 lcp->want_magic = GenerateMagic(); 767 break; 768 case MODE_REJ: 769 log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic); 770 lcp->want_magic = 0; 771 lcp->his_reject |= (1 << type); 772 break; 773 } 774 break; 775 776 case TY_PROTOCOMP: 777 log_Printf(LogLCP, "%s\n", request); 778 779 switch (mode_type) { 780 case MODE_REQ: 781 if (IsAccepted(lcp->cfg.protocomp)) { 782 lcp->his_protocomp = 1; 783 memcpy(dec->ackend, cp, 2); 784 dec->ackend += 2; 785 } else { 786 #ifdef OLDMST 787 /* 788 * MorningStar before v1.3 needs NAK 789 */ 790 memcpy(dec->nakend, cp, 2); 791 dec->nakend += 2; 792 #else 793 goto reqreject; 794 #endif 795 } 796 break; 797 case MODE_NAK: 798 case MODE_REJ: 799 lcp->want_protocomp = 0; 800 lcp->his_reject |= (1 << type); 801 break; 802 } 803 break; 804 805 case TY_ACFCOMP: 806 log_Printf(LogLCP, "%s\n", request); 807 switch (mode_type) { 808 case MODE_REQ: 809 if (IsAccepted(lcp->cfg.acfcomp)) { 810 lcp->his_acfcomp = 1; 811 memcpy(dec->ackend, cp, 2); 812 dec->ackend += 2; 813 } else { 814 #ifdef OLDMST 815 /* 816 * MorningStar before v1.3 needs NAK 817 */ 818 memcpy(dec->nakend, cp, 2); 819 dec->nakend += 2; 820 #else 821 goto reqreject; 822 #endif 823 } 824 break; 825 case MODE_NAK: 826 case MODE_REJ: 827 lcp->want_acfcomp = 0; 828 lcp->his_reject |= (1 << type); 829 break; 830 } 831 break; 832 833 case TY_SDP: 834 log_Printf(LogLCP, "%s\n", request); 835 switch (mode_type) { 836 case MODE_REQ: 837 case MODE_NAK: 838 case MODE_REJ: 839 break; 840 } 841 break; 842 843 case TY_CALLBACK: 844 if (length == 2) 845 op = CALLBACK_NONE; 846 else 847 op = (int)cp[2]; 848 sz = length - 3; 849 switch (op) { 850 case CALLBACK_AUTH: 851 log_Printf(LogLCP, "%s Auth\n", request); 852 break; 853 case CALLBACK_DIALSTRING: 854 log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3); 855 break; 856 case CALLBACK_LOCATION: 857 log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3); 858 break; 859 case CALLBACK_E164: 860 log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3); 861 break; 862 case CALLBACK_NAME: 863 log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3); 864 break; 865 case CALLBACK_CBCP: 866 log_Printf(LogLCP, "%s CBCP\n", request); 867 break; 868 default: 869 log_Printf(LogLCP, "%s ???\n", request); 870 break; 871 } 872 873 switch (mode_type) { 874 case MODE_REQ: 875 callback_req = 1; 876 if (p->type != PHYS_DIRECT) 877 goto reqreject; 878 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) && 879 (op != CALLBACK_AUTH || p->link.lcp.auth_ineed) && 880 (op != CALLBACK_E164 || 881 E164ok(&p->dl->cfg.callback, cp + 3, sz))) { 882 lcp->his_callback.opmask = CALLBACK_BIT(op); 883 if (sz > sizeof lcp->his_callback.msg - 1) { 884 sz = sizeof lcp->his_callback.msg - 1; 885 log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz); 886 } 887 memcpy(lcp->his_callback.msg, cp + 3, sz); 888 lcp->his_callback.msg[sz] = '\0'; 889 memcpy(dec->ackend, cp, sz + 3); 890 dec->ackend += sz + 3; 891 } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) && 892 p->link.lcp.auth_ineed) { 893 *dec->nakend++ = *cp; 894 *dec->nakend++ = 3; 895 *dec->nakend++ = CALLBACK_AUTH; 896 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) { 897 *dec->nakend++ = *cp; 898 *dec->nakend++ = 3; 899 *dec->nakend++ = CALLBACK_CBCP; 900 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) { 901 *dec->nakend++ = *cp; 902 *dec->nakend++ = 3; 903 *dec->nakend++ = CALLBACK_E164; 904 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) { 905 log_Printf(LogWARN, "Cannot insist on auth callback without" 906 " PAP or CHAP enabled !\n"); 907 *dec->nakend++ = *cp; 908 *dec->nakend++ = 2; 909 } else 910 goto reqreject; 911 break; 912 case MODE_NAK: 913 /* We don't do what he NAKs want, we do things in our preferred order */ 914 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) 915 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH); 916 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) 917 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP); 918 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) 919 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164); 920 if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) { 921 log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n"); 922 lcp->want_callback.opmask = 0; 923 } else if (!lcp->want_callback.opmask) { 924 log_Printf(LogPHASE, "Peer NAKd last configured callback\n"); 925 fsm_Close(&lcp->fsm); 926 } 927 break; 928 case MODE_REJ: 929 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) { 930 lcp->his_reject |= (1 << type); 931 lcp->want_callback.opmask = 0; 932 } else { 933 log_Printf(LogPHASE, "Peer rejected *required* callback\n"); 934 fsm_Close(&lcp->fsm); 935 } 936 break; 937 } 938 break; 939 940 case TY_SHORTSEQ: 941 mp = &lcp->fsm.bundle->ncp.mp; 942 log_Printf(LogLCP, "%s\n", request); 943 944 switch (mode_type) { 945 case MODE_REQ: 946 if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) { 947 lcp->his_shortseq = 1; 948 memcpy(dec->ackend, cp, length); 949 dec->ackend += length; 950 } else 951 goto reqreject; 952 break; 953 case MODE_NAK: 954 /* 955 * He's trying to get us to ask for short sequence numbers. 956 * We ignore the NAK and honour our configuration file instead. 957 */ 958 break; 959 case MODE_REJ: 960 lcp->his_reject |= (1 << type); 961 lcp->want_shortseq = 0; /* For when we hit MP */ 962 break; 963 } 964 break; 965 966 case TY_ENDDISC: 967 log_Printf(LogLCP, "%s %s\n", request, 968 mp_Enddisc(cp[2], cp + 3, length - 3)); 969 switch (mode_type) { 970 case MODE_REQ: 971 if (!p) { 972 log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n"); 973 goto reqreject; 974 } else if (length-3 < sizeof p->dl->peer.enddisc.address && 975 cp[2] <= MAX_ENDDISC_CLASS) { 976 p->dl->peer.enddisc.class = cp[2]; 977 p->dl->peer.enddisc.len = length-3; 978 memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3); 979 p->dl->peer.enddisc.address[length - 3] = '\0'; 980 /* XXX: If mp->active, compare and NAK with mp->peer ? */ 981 memcpy(dec->ackend, cp, length); 982 dec->ackend += length; 983 } else { 984 if (cp[2] > MAX_ENDDISC_CLASS) 985 log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n", 986 cp[2]); 987 else 988 log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n", 989 (long)(sizeof p->dl->peer.enddisc.address - 1)); 990 goto reqreject; 991 } 992 break; 993 994 case MODE_NAK: /* Treat this as a REJ, we don't vary or disc */ 995 case MODE_REJ: 996 lcp->his_reject |= (1 << type); 997 break; 998 } 999 break; 1000 1001 default: 1002 sz = (sizeof desc - 2) / 2; 1003 if (sz > length - 2) 1004 sz = length - 2; 1005 pos = 0; 1006 desc[0] = sz ? ' ' : '\0'; 1007 for (pos = 0; sz--; pos++) 1008 sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]); 1009 1010 log_Printf(LogLCP, "%s%s\n", request, desc); 1011 1012 if (mode_type == MODE_REQ) { 1013 reqreject: 1014 if (length > sizeof dec->rej - (dec->rejend - dec->rej)) { 1015 length = sizeof dec->rej - (dec->rejend - dec->rej); 1016 log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n", 1017 cp[1], length); 1018 } 1019 memcpy(dec->rejend, cp, length); 1020 dec->rejend += length; 1021 lcp->my_reject |= (1 << type); 1022 if (length != cp[1]) 1023 length = 0; /* force our way out of the loop */ 1024 } 1025 break; 1026 } 1027 plen -= length; 1028 cp += length; 1029 } 1030 1031 if (mode_type != MODE_NOP) { 1032 if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT && 1033 p->dl->cfg.callback.opmask && !callback_req && 1034 !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) { 1035 /* We *REQUIRE* that the peer requests callback */ 1036 *dec->nakend++ = TY_CALLBACK; 1037 *dec->nakend++ = 3; 1038 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) && 1039 p->link.lcp.auth_ineed) 1040 *dec->nakend++ = CALLBACK_AUTH; 1041 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) 1042 *dec->nakend++ = CALLBACK_CBCP; 1043 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) 1044 *dec->nakend++ = CALLBACK_E164; 1045 else { 1046 log_Printf(LogWARN, "Cannot insist on auth callback without" 1047 " PAP or CHAP enabled !\n"); 1048 dec->nakend[-1] = 2; /* XXX: Silly ! */ 1049 } 1050 } 1051 if (dec->rejend != dec->rej) { 1052 /* rejects are preferred */ 1053 dec->ackend = dec->ack; 1054 dec->nakend = dec->nak; 1055 } else if (dec->nakend != dec->nak) 1056 /* then NAKs */ 1057 dec->ackend = dec->ack; 1058 } 1059 } 1060 1061 void 1062 lcp_Input(struct lcp *lcp, struct mbuf * bp) 1063 { 1064 /* Got PROTO_LCP from link */ 1065 fsm_Input(&lcp->fsm, bp); 1066 } 1067