ipcp.c revision 31514
1/* 2 * PPP IP Control Protocol (IPCP) 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: ipcp.c,v 1.38 1997/11/22 03:37:34 brian Exp $ 21 * 22 * TODO: 23 * o More RFC1772 backwoard compatibility 24 */ 25#include <sys/param.h> 26#include <netinet/in_systm.h> 27#include <netinet/in.h> 28#include <netinet/ip.h> 29#include <arpa/inet.h> 30#include <sys/socket.h> 31#include <netdb.h> 32 33#include <limits.h> 34#include <stdio.h> 35#include <string.h> 36#include <time.h> 37#include <unistd.h> 38 39#include "command.h" 40#include "mbuf.h" 41#include "log.h" 42#include "defs.h" 43#include "timer.h" 44#include "fsm.h" 45#include "lcpproto.h" 46#include "lcp.h" 47#include "ipcp.h" 48#include "slcompress.h" 49#include "os.h" 50#include "phase.h" 51#include "loadalias.h" 52#include "vars.h" 53#include "vjcomp.h" 54#include "ip.h" 55#include "throughput.h" 56 57#ifndef NOMSEXT 58struct in_addr ns_entries[2]; 59struct in_addr nbns_entries[2]; 60#endif 61 62struct ipcpstate IpcpInfo; 63struct in_range DefMyAddress; 64struct in_range DefHisAddress; 65struct in_addr TriggerAddress; 66int HaveTriggerAddress; 67 68static void IpcpSendConfigReq(struct fsm *); 69static void IpcpSendTerminateAck(struct fsm *); 70static void IpcpSendTerminateReq(struct fsm *); 71static void IpcpDecodeConfig(u_char *, int, int); 72static void IpcpLayerStart(struct fsm *); 73static void IpcpLayerFinish(struct fsm *); 74static void IpcpLayerUp(struct fsm *); 75static void IpcpLayerDown(struct fsm *); 76static void IpcpInitRestartCounter(struct fsm *); 77 78#define REJECTED(p, x) (p->his_reject & (1<<x)) 79 80struct fsm IpcpFsm = { 81 "IPCP", 82 PROTO_IPCP, 83 IPCP_MAXCODE, 84 OPEN_ACTIVE, 85 ST_INITIAL, 86 0, 0, 0, 87 88 0, 89 {0, 0, 0, NULL, NULL, NULL}, 90 {0, 0, 0, NULL, NULL, NULL}, 91 LogIPCP, 92 93 IpcpLayerUp, 94 IpcpLayerDown, 95 IpcpLayerStart, 96 IpcpLayerFinish, 97 IpcpInitRestartCounter, 98 IpcpSendConfigReq, 99 IpcpSendTerminateReq, 100 IpcpSendTerminateAck, 101 IpcpDecodeConfig, 102}; 103 104static const char *cftypes[] = { 105 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 106 "???", 107 "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 108 "COMPPROTO", /* 2: IP-Compression-Protocol */ 109 "IPADDR", /* 3: IP-Address */ 110}; 111 112#define NCFTYPES (sizeof(cftypes)/sizeof(char *)) 113 114static const char *cftypes128[] = { 115 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 116 "???", 117 "PRIDNS", /* 129: Primary DNS Server Address */ 118 "PRINBNS", /* 130: Primary NBNS Server Address */ 119 "SECDNS", /* 131: Secondary DNS Server Address */ 120 "SECNBNS", /* 132: Secondary NBNS Server Address */ 121}; 122 123#define NCFTYPES128 (sizeof(cftypes)/sizeof(char *)) 124 125struct pppThroughput throughput; 126 127void 128IpcpAddInOctets(int n) 129{ 130 throughput_addin(&throughput, n); 131} 132 133void 134IpcpAddOutOctets(int n) 135{ 136 throughput_addout(&throughput, n); 137} 138 139int 140ReportIpcpStatus(struct cmdargs const *arg) 141{ 142 struct ipcpstate *icp = &IpcpInfo; 143 struct fsm *fp = &IpcpFsm; 144 145 if (!VarTerm) 146 return 1; 147 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]); 148 fprintf(VarTerm, " his side: %s, %s\n", 149 inet_ntoa(icp->his_ipaddr), vj2asc(icp->his_compproto)); 150 fprintf(VarTerm, " my side: %s, %s\n", 151 inet_ntoa(icp->want_ipaddr), vj2asc(icp->want_compproto)); 152 153 fprintf(VarTerm, "Defaults:\n"); 154 fprintf(VarTerm, " My Address: %s/%d\n", 155 inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width); 156 fprintf(VarTerm, " His Address: %s/%d\n", 157 inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width); 158 if (HaveTriggerAddress) 159 fprintf(VarTerm, " Negotiation(trigger): %s\n", inet_ntoa(TriggerAddress)); 160 else 161 fprintf(VarTerm, " Negotiation(trigger): MYADDR\n"); 162 163 fprintf(VarTerm, "\n"); 164 throughput_disp(&throughput, VarTerm); 165 166 return 0; 167} 168 169void 170IpcpDefAddress() 171{ 172 struct hostent *hp; 173 char name[200]; 174 175 memset(&DefMyAddress, '\0', sizeof(DefMyAddress)); 176 memset(&DefHisAddress, '\0', sizeof(DefHisAddress)); 177 TriggerAddress.s_addr = 0; 178 HaveTriggerAddress = 0; 179 if (gethostname(name, sizeof(name)) == 0) { 180 hp = gethostbyname(name); 181 if (hp && hp->h_addrtype == AF_INET) { 182 memcpy(&DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length); 183 } 184 } 185} 186 187void 188IpcpInit() 189{ 190 struct ipcpstate *icp = &IpcpInfo; 191 192 FsmInit(&IpcpFsm); 193 memset(icp, '\0', sizeof(struct ipcpstate)); 194 if ((mode & MODE_DEDICATED) && !GetLabel()) { 195 icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0; 196 } else { 197 icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr; 198 icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr; 199 } 200 201 /* 202 * Some implementations of PPP require that we send a 203 * *special* value as our address, even though the rfc specifies 204 * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 205 */ 206 if (HaveTriggerAddress) { 207 icp->want_ipaddr.s_addr = TriggerAddress.s_addr; 208 LogPrintf(LogIPCP, "Using trigger address %s\n", inet_ntoa(TriggerAddress)); 209 } 210 if (Enabled(ConfVjcomp)) 211 icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8) | 1; 212 else 213 icp->want_compproto = 0; 214 icp->heis1172 = 0; 215 IpcpFsm.maxconfig = 10; 216 throughput_init(&throughput); 217} 218 219static void 220IpcpInitRestartCounter(struct fsm * fp) 221{ 222 fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 223 fp->restart = 5; 224} 225 226static void 227IpcpSendConfigReq(struct fsm * fp) 228{ 229 u_char *cp; 230 struct ipcpstate *icp = &IpcpInfo; 231 struct lcp_opt o; 232 233 cp = ReqBuff; 234 LogPrintf(LogIPCP, "IpcpSendConfigReq\n"); 235 if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR)) { 236 o.id = TY_IPADDR; 237 o.len = 6; 238 *(u_long *)o.data = icp->want_ipaddr.s_addr; 239 cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id], 240 inet_ntoa(icp->want_ipaddr)); 241 } 242 243 if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) { 244 const char *args; 245 o.id = TY_COMPPROTO; 246 if (icp->heis1172) { 247 o.len = 4; 248 *(u_short *)o.data = htons(PROTO_VJCOMP); 249 args = ""; 250 } else { 251 o.len = 6; 252 *(u_long *)o.data = htonl(icp->want_compproto); 253 args = vj2asc(icp->want_compproto); 254 } 255 cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id], args); 256 } 257 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 258} 259 260static void 261IpcpSendTerminateReq(struct fsm * fp) 262{ 263 /* XXX: No code yet */ 264} 265 266static void 267IpcpSendTerminateAck(struct fsm * fp) 268{ 269 LogPrintf(LogIPCP, "IpcpSendTerminateAck\n"); 270 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 271} 272 273static void 274IpcpLayerStart(struct fsm * fp) 275{ 276 LogPrintf(LogIPCP, "IpcpLayerStart.\n"); 277} 278 279static void 280IpcpLayerFinish(struct fsm * fp) 281{ 282 LogPrintf(LogIPCP, "IpcpLayerFinish.\n"); 283 reconnect(RECON_FALSE); 284 LcpClose(); 285 NewPhase(PHASE_TERMINATE); 286} 287 288static void 289IpcpLayerDown(struct fsm * fp) 290{ 291 LogPrintf(LogIPCP, "IpcpLayerDown.\n"); 292 throughput_stop(&throughput); 293 throughput_log(&throughput, LogIPCP, NULL); 294} 295 296/* 297 * Called when IPCP has reached to OPEN state 298 */ 299static void 300IpcpLayerUp(struct fsm * fp) 301{ 302 char tbuff[100]; 303 304 Prompt(); 305 LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state); 306 snprintf(tbuff, sizeof(tbuff), "myaddr = %s ", 307 inet_ntoa(IpcpInfo.want_ipaddr)); 308 309 if (IpcpInfo.his_compproto >> 16 == PROTO_VJCOMP) 310 VjInit((IpcpInfo.his_compproto >> 8) & 255); 311 312 LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n", 313 tbuff, inet_ntoa(IpcpInfo.his_ipaddr)); 314 if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask) < 0) { 315 if (VarTerm) 316 LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n"); 317 return; 318 } 319#ifndef NOALIAS 320 if (mode & MODE_ALIAS) 321 VarPacketAliasSetAddress(IpcpInfo.want_ipaddr); 322#endif 323 OsLinkup(); 324 throughput_start(&throughput); 325 StartIdleTimer(); 326} 327 328void 329IpcpUp() 330{ 331 FsmUp(&IpcpFsm); 332 LogPrintf(LogIPCP, "IPCP Up event!!\n"); 333} 334 335void 336IpcpOpen() 337{ 338 FsmOpen(&IpcpFsm); 339} 340 341static int 342AcceptableAddr(struct in_range * prange, struct in_addr ipaddr) 343{ 344 LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr)); 345 LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr)); 346 LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr)); 347 LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange-> 348 mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr)); 349 return (prange->ipaddr.s_addr & prange->mask.s_addr) == 350 (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 351} 352 353static void 354IpcpDecodeConfig(u_char * cp, int plen, int mode_type) 355{ 356 int type, length; 357 u_long *lp, compproto; 358 struct compreq *pcomp; 359 struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req; 360 char tbuff[100]; 361 char tbuff2[100]; 362 363 ackp = AckBuff; 364 nakp = NakBuff; 365 rejp = RejBuff; 366 367 while (plen >= sizeof(struct fsmconfig)) { 368 type = *cp; 369 length = cp[1]; 370 if (type < NCFTYPES) 371 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length); 372 else if (type > 128 && type < 128 + NCFTYPES128) 373 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes128[type], length); 374 else 375 snprintf(tbuff, sizeof(tbuff), " ??? "); 376 377 switch (type) { 378 case TY_IPADDR: /* RFC1332 */ 379 lp = (u_long *) (cp + 2); 380 ipaddr.s_addr = *lp; 381 LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 382 383 switch (mode_type) { 384 case MODE_REQ: 385 if (!AcceptableAddr(&DefHisAddress, ipaddr)) { 386 /* 387 * If destination address is not acceptable, insist to use what we 388 * want to use. 389 */ 390 memcpy(nakp, cp, 2); 391 memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length); 392 nakp += length; 393 break; 394 } 395 IpcpInfo.his_ipaddr = ipaddr; 396 memcpy(ackp, cp, length); 397 ackp += length; 398 break; 399 case MODE_NAK: 400 if (AcceptableAddr(&DefMyAddress, ipaddr)) { 401 402 /* 403 * Use address suggested by peer. 404 */ 405 snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff, 406 inet_ntoa(IpcpInfo.want_ipaddr)); 407 LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 408 IpcpInfo.want_ipaddr = ipaddr; 409 } 410 break; 411 case MODE_REJ: 412 IpcpInfo.his_reject |= (1 << type); 413 break; 414 } 415 break; 416 case TY_COMPPROTO: 417 lp = (u_long *) (cp + 2); 418 compproto = htonl(*lp); 419 LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 420 421 switch (mode_type) { 422 case MODE_REQ: 423 if (!Acceptable(ConfVjcomp)) { 424 memcpy(rejp, cp, length); 425 rejp += length; 426 } else { 427 pcomp = (struct compreq *) (cp + 2); 428 switch (length) { 429 case 4: /* RFC1172 */ 430 if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 431 LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 432 IpcpInfo.heis1172 = 1; 433 IpcpInfo.his_compproto = compproto; 434 memcpy(ackp, cp, length); 435 ackp += length; 436 } else { 437 memcpy(nakp, cp, 2); 438 pcomp->proto = htons(PROTO_VJCOMP); 439 memcpy(nakp+2, &pcomp, 2); 440 nakp += length; 441 } 442 break; 443 case 6: /* RFC1332 */ 444 if (ntohs(pcomp->proto) == PROTO_VJCOMP 445 && pcomp->slots < MAX_STATES && pcomp->slots > 2) { 446 IpcpInfo.his_compproto = compproto; 447 IpcpInfo.heis1172 = 0; 448 memcpy(ackp, cp, length); 449 ackp += length; 450 } else { 451 memcpy(nakp, cp, 2); 452 pcomp->proto = htons(PROTO_VJCOMP); 453 pcomp->slots = MAX_STATES - 1; 454 pcomp->compcid = 0; 455 memcpy(nakp+2, &pcomp, sizeof(pcomp)); 456 nakp += length; 457 } 458 break; 459 default: 460 memcpy(rejp, cp, length); 461 rejp += length; 462 break; 463 } 464 } 465 break; 466 case MODE_NAK: 467 LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 468 tbuff, IpcpInfo.want_compproto, compproto); 469 IpcpInfo.want_compproto = compproto; 470 break; 471 case MODE_REJ: 472 IpcpInfo.his_reject |= (1 << type); 473 break; 474 } 475 break; 476 case TY_IPADDRS: /* RFC1172 */ 477 lp = (u_long *) (cp + 2); 478 ipaddr.s_addr = *lp; 479 lp = (u_long *) (cp + 6); 480 dstipaddr.s_addr = *lp; 481 snprintf(tbuff2, sizeof(tbuff2), "%s %s,", tbuff, inet_ntoa(ipaddr)); 482 LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 483 484 switch (mode_type) { 485 case MODE_REQ: 486 IpcpInfo.his_ipaddr = ipaddr; 487 IpcpInfo.want_ipaddr = dstipaddr; 488 memcpy(ackp, cp, length); 489 ackp += length; 490 break; 491 case MODE_NAK: 492 snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s", tbuff, 493 inet_ntoa(IpcpInfo.want_ipaddr)); 494 LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 495 IpcpInfo.want_ipaddr = ipaddr; 496 IpcpInfo.his_ipaddr = dstipaddr; 497 break; 498 case MODE_REJ: 499 IpcpInfo.his_reject |= (1 << type); 500 break; 501 } 502 break; 503 504 /* 505 * MS extensions for MS's PPP 506 */ 507 508#ifndef NOMSEXT 509 case TY_PRIMARY_DNS: /* MS PPP DNS negotiation hack */ 510 case TY_SECONDARY_DNS: 511 if (!Enabled(ConfMSExt)) { 512 LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n"); 513 IpcpInfo.my_reject |= (1 << type); 514 memcpy(rejp, cp, length); 515 rejp += length; 516 break; 517 } 518 switch (mode_type) { 519 case MODE_REQ: 520 lp = (u_long *) (cp + 2); 521 dnsstuff.s_addr = *lp; 522 ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS) ? 1 : 0)].s_addr; 523 if (dnsstuff.s_addr != ms_info_req.s_addr) { 524 525 /* 526 * So the client has got the DNS stuff wrong (first request) so 527 * we'll tell 'em how it is 528 */ 529 memcpy(nakp, cp, 2); /* copy first two (type/length) */ 530 LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n", 531 type, 532 inet_ntoa(dnsstuff), 533 inet_ntoa(ms_info_req)); 534 memcpy(nakp+2, &ms_info_req, length); 535 nakp += length; 536 break; 537 } 538 539 /* 540 * Otherwise they have it right (this time) so we send a ack packet 541 * back confirming it... end of story 542 */ 543 LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n", 544 type, 545 inet_ntoa(ms_info_req)); 546 memcpy(ackp, cp, length); 547 ackp += length; 548 break; 549 case MODE_NAK: /* what does this mean?? */ 550 LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type); 551 break; 552 case MODE_REJ: /* confused?? me to :) */ 553 LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type); 554 break; 555 } 556 break; 557 558 case TY_PRIMARY_NBNS: /* MS PPP NetBIOS nameserver hack */ 559 case TY_SECONDARY_NBNS: 560 if (!Enabled(ConfMSExt)) { 561 LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n"); 562 IpcpInfo.my_reject |= (1 << type); 563 memcpy(rejp, cp, length); 564 rejp += length; 565 break; 566 } 567 switch (mode_type) { 568 case MODE_REQ: 569 lp = (u_long *) (cp + 2); 570 dnsstuff.s_addr = *lp; 571 ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS) ? 1 : 0)].s_addr; 572 if (dnsstuff.s_addr != ms_info_req.s_addr) { 573 memcpy(nakp, cp, 2); 574 memcpy(nakp+2, &ms_info_req.s_addr, length); 575 LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n", 576 type, 577 inet_ntoa(dnsstuff), 578 inet_ntoa(ms_info_req)); 579 nakp += length; 580 break; 581 } 582 LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n", 583 type, 584 inet_ntoa(ms_info_req)); 585 memcpy(ackp, cp, length); 586 ackp += length; 587 break; 588 case MODE_NAK: 589 LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 590 break; 591 case MODE_REJ: 592 LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 593 break; 594 } 595 break; 596 597#endif 598 599 default: 600 IpcpInfo.my_reject |= (1 << type); 601 memcpy(rejp, cp, length); 602 rejp += length; 603 break; 604 } 605 plen -= length; 606 cp += length; 607 } 608} 609 610void 611IpcpInput(struct mbuf * bp) 612{ 613 FsmInput(&IpcpFsm, bp); 614} 615