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