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.67 1998/10/22 02:32:49 brian Exp $ 21 * 22 * TODO: 23 * o More RFC1772 backward 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 <net/route.h> 32 #include <netdb.h> 33 #include <net/if.h> 34 #include <sys/sockio.h> 35 #include <sys/un.h> 36 #include <arpa/nameser.h> 37 38 #include <fcntl.h> 39 #include <resolv.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <sys/errno.h> 43 #include <termios.h> 44 #include <unistd.h> 45 46 #ifndef NOALIAS 47 #ifdef __OpenBSD__ 48 #include "alias.h" 49 #else 50 #include <alias.h> 51 #endif 52 #endif 53 #include "ua.h" 54 #include "defs.h" 55 #include "command.h" 56 #include "mbuf.h" 57 #include "log.h" 58 #include "timer.h" 59 #include "fsm.h" 60 #include "lcpproto.h" 61 #include "lcp.h" 62 #include "iplist.h" 63 #include "throughput.h" 64 #include "slcompress.h" 65 #include "lqr.h" 66 #include "hdlc.h" 67 #include "ipcp.h" 68 #include "filter.h" 69 #include "descriptor.h" 70 #include "vjcomp.h" 71 #include "async.h" 72 #include "ccp.h" 73 #include "link.h" 74 #include "physical.h" 75 #include "mp.h" 76 #include "bundle.h" 77 #include "id.h" 78 #include "arp.h" 79 #include "systems.h" 80 #include "prompt.h" 81 #include "route.h" 82 #include "iface.h" 83 84 #undef REJECTED 85 #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 86 #define issep(ch) ((ch) == ' ' || (ch) == '\t') 87 #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 88 89 struct compreq { 90 u_short proto; 91 u_char slots; 92 u_char compcid; 93 }; 94 95 static int IpcpLayerUp(struct fsm *); 96 static void IpcpLayerDown(struct fsm *); 97 static void IpcpLayerStart(struct fsm *); 98 static void IpcpLayerFinish(struct fsm *); 99 static void IpcpInitRestartCounter(struct fsm *); 100 static void IpcpSendConfigReq(struct fsm *); 101 static void IpcpSentTerminateReq(struct fsm *); 102 static void IpcpSendTerminateAck(struct fsm *, u_char); 103 static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 104 struct fsm_decode *); 105 106 static struct fsm_callbacks ipcp_Callbacks = { 107 IpcpLayerUp, 108 IpcpLayerDown, 109 IpcpLayerStart, 110 IpcpLayerFinish, 111 IpcpInitRestartCounter, 112 IpcpSendConfigReq, 113 IpcpSentTerminateReq, 114 IpcpSendTerminateAck, 115 IpcpDecodeConfig, 116 fsm_NullRecvResetReq, 117 fsm_NullRecvResetAck 118 }; 119 120 static const char *cftypes[] = { 121 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 122 "???", 123 "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 124 "COMPPROTO", /* 2: IP-Compression-Protocol */ 125 "IPADDR", /* 3: IP-Address */ 126 }; 127 128 #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 129 130 static const char *cftypes128[] = { 131 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 132 "???", 133 "PRIDNS", /* 129: Primary DNS Server Address */ 134 "PRINBNS", /* 130: Primary NBNS Server Address */ 135 "SECDNS", /* 131: Secondary DNS Server Address */ 136 "SECNBNS", /* 132: Secondary NBNS Server Address */ 137 }; 138 139 #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 140 141 void 142 ipcp_AddInOctets(struct ipcp *ipcp, int n) 143 { 144 throughput_addin(&ipcp->throughput, n); 145 } 146 147 void 148 ipcp_AddOutOctets(struct ipcp *ipcp, int n) 149 { 150 throughput_addout(&ipcp->throughput, n); 151 } 152 153 static void 154 getdns(struct ipcp *ipcp, struct in_addr addr[2]) 155 { 156 FILE *fp; 157 158 addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 159 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 160 char buf[LINE_LEN], *cp, *end; 161 int n; 162 163 n = 0; 164 buf[sizeof buf - 1] = '\0'; 165 while (fgets(buf, sizeof buf - 1, fp)) { 166 if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 167 for (cp = buf + 11; issep(*cp); cp++) 168 ; 169 for (end = cp; isip(*end); end++) 170 ; 171 *end = '\0'; 172 if (inet_aton(cp, addr+n) && ++n == 2) 173 break; 174 } 175 } 176 if (n == 1) 177 addr[1] = addr[0]; 178 fclose(fp); 179 } 180 } 181 182 static int 183 setdns(struct ipcp *ipcp, struct in_addr addr[2]) 184 { 185 FILE *fp; 186 char wbuf[LINE_LEN + 54]; 187 int wlen; 188 189 if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 190 struct in_addr old[2]; 191 192 getdns(ipcp, old); 193 if (addr[0].s_addr == INADDR_ANY) 194 addr[0] = old[0]; 195 if (addr[1].s_addr == INADDR_ANY) 196 addr[1] = old[1]; 197 } 198 199 if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 200 log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n", 201 _PATH_RESCONF); 202 return 0; 203 } 204 205 wlen = 0; 206 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 207 char buf[LINE_LEN]; 208 int len; 209 210 buf[sizeof buf - 1] = '\0'; 211 while (fgets(buf, sizeof buf - 1, fp)) { 212 if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 213 len = strlen(buf); 214 if (len > sizeof wbuf - wlen) { 215 log_Printf(LogWARN, "%s: Can only cope with max file size %d\n", 216 _PATH_RESCONF, LINE_LEN); 217 fclose(fp); 218 return 0; 219 } 220 memcpy(wbuf + wlen, buf, len); 221 wlen += len; 222 } 223 } 224 fclose(fp); 225 } 226 227 if (addr[0].s_addr != INADDR_ANY) { 228 snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 229 inet_ntoa(addr[0])); 230 log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 231 wlen += strlen(wbuf + wlen); 232 } 233 234 if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 235 snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 236 inet_ntoa(addr[1])); 237 log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 238 wlen += strlen(wbuf + wlen); 239 } 240 241 if (wlen) { 242 int fd; 243 244 if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 245 if (write(fd, wbuf, wlen) != wlen) { 246 log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 247 close(fd); 248 return 0; 249 } 250 if (ftruncate(fd, wlen) == -1) { 251 log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 252 close(fd); 253 return 0; 254 } 255 close(fd); 256 } else { 257 log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 258 return 0; 259 } 260 } 261 262 return 1; 263 } 264 265 int 266 ipcp_Show(struct cmdargs const *arg) 267 { 268 struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 269 270 prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 271 State2Nam(ipcp->fsm.state)); 272 if (ipcp->fsm.state == ST_OPENED) { 273 prompt_Printf(arg->prompt, " His side: %s, %s\n", 274 inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 275 prompt_Printf(arg->prompt, " My side: %s, %s\n", 276 inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 277 } 278 279 if (ipcp->route) { 280 prompt_Printf(arg->prompt, "\n"); 281 route_ShowSticky(arg->prompt, ipcp->route); 282 } 283 284 prompt_Printf(arg->prompt, "\nDefaults:\n"); 285 prompt_Printf(arg->prompt, " My Address: %s/%d", 286 inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width); 287 288 if (ipcp->cfg.HaveTriggerAddress) 289 prompt_Printf(arg->prompt, " (trigger with %s)", 290 inet_ntoa(ipcp->cfg.TriggerAddress)); 291 prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot " 292 "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 293 ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 294 295 if (iplist_isvalid(&ipcp->cfg.peer_list)) 296 prompt_Printf(arg->prompt, " His Address: %s\n", 297 ipcp->cfg.peer_list.src); 298 else 299 prompt_Printf(arg->prompt, " His Address: %s/%d\n", 300 inet_ntoa(ipcp->cfg.peer_range.ipaddr), 301 ipcp->cfg.peer_range.width); 302 303 prompt_Printf(arg->prompt, " DNS: %s, ", 304 inet_ntoa(ipcp->cfg.ns.dns[0])); 305 prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]), 306 command_ShowNegval(ipcp->cfg.ns.dns_neg)); 307 prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 308 inet_ntoa(ipcp->cfg.ns.nbns[0])); 309 prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); 310 311 prompt_Printf(arg->prompt, "\n"); 312 throughput_disp(&ipcp->throughput, arg->prompt); 313 314 return 0; 315 } 316 317 int 318 ipcp_vjset(struct cmdargs const *arg) 319 { 320 if (arg->argc != arg->argn+2) 321 return -1; 322 if (!strcasecmp(arg->argv[arg->argn], "slots")) { 323 int slots; 324 325 slots = atoi(arg->argv[arg->argn+1]); 326 if (slots < 4 || slots > 16) 327 return 1; 328 arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 329 return 0; 330 } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 331 if (!strcasecmp(arg->argv[arg->argn+1], "on")) 332 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 333 else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 334 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 335 else 336 return 2; 337 return 0; 338 } 339 return -1; 340 } 341 342 void 343 ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 344 const struct fsm_parent *parent) 345 { 346 struct hostent *hp; 347 char name[MAXHOSTNAMELEN]; 348 static const char *timer_names[] = 349 {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 350 351 fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP, 352 bundle, l, parent, &ipcp_Callbacks, timer_names); 353 354 ipcp->route = NULL; 355 ipcp->cfg.vj.slots = DEF_VJ_STATES; 356 ipcp->cfg.vj.slotcomp = 1; 357 memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 358 if (gethostname(name, sizeof name) == 0) { 359 hp = gethostbyname(name); 360 if (hp && hp->h_addrtype == AF_INET) 361 memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 362 } 363 ipcp->cfg.netmask.s_addr = INADDR_ANY; 364 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 365 iplist_setsrc(&ipcp->cfg.peer_list, ""); 366 ipcp->cfg.HaveTriggerAddress = 0; 367 368 ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 369 ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 370 ipcp->cfg.ns.dns_neg = 0; 371 ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 372 ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 373 374 ipcp->cfg.fsmretry = DEF_FSMRETRY; 375 ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 376 377 memset(&ipcp->vj, '\0', sizeof ipcp->vj); 378 379 throughput_init(&ipcp->throughput); 380 memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 381 ipcp_Setup(ipcp); 382 } 383 384 void 385 ipcp_SetLink(struct ipcp *ipcp, struct link *l) 386 { 387 ipcp->fsm.link = l; 388 } 389 390 void 391 ipcp_Setup(struct ipcp *ipcp) 392 { 393 struct iface *iface = ipcp->fsm.bundle->iface; 394 int pos, n; 395 396 ipcp->fsm.open_mode = 0; 397 ipcp->fsm.maxconfig = 10; 398 399 if (iplist_isvalid(&ipcp->cfg.peer_list)) { 400 /* Try to give the peer a previously configured IP address */ 401 for (n = 0; n < iface->in_addrs; n++) { 402 pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd); 403 if (pos != -1) { 404 ipcp->cfg.peer_range.ipaddr = 405 iplist_setcurpos(&ipcp->cfg.peer_list, pos); 406 break; 407 } 408 } 409 if (n == iface->in_addrs) 410 /* Ok, so none of 'em fit.... pick a random one */ 411 ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 412 413 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 414 ipcp->cfg.peer_range.width = 32; 415 } 416 417 ipcp->heis1172 = 0; 418 419 ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 420 ipcp->peer_compproto = 0; 421 422 if (ipcp->cfg.HaveTriggerAddress) { 423 /* 424 * Some implementations of PPP require that we send a 425 * *special* value as our address, even though the rfc specifies 426 * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 427 */ 428 ipcp->my_ip = ipcp->cfg.TriggerAddress; 429 log_Printf(LogIPCP, "Using trigger address %s\n", 430 inet_ntoa(ipcp->cfg.TriggerAddress)); 431 } else { 432 /* 433 * Otherwise, if we've used an IP number before and it's still within 434 * the network specified on the ``set ifaddr'' line, we really 435 * want to keep that IP number so that we can keep any existing 436 * connections that are bound to that IP (assuming we're not 437 * ``iface-alias''ing). 438 */ 439 for (n = 0; n < iface->in_addrs; n++) 440 if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) == 441 (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) { 442 ipcp->my_ip = iface->in_addr[n].ifa; 443 break; 444 } 445 if (n == iface->in_addrs) 446 ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 447 } 448 449 if (IsEnabled(ipcp->cfg.vj.neg)) 450 ipcp->my_compproto = (PROTO_VJCOMP << 16) + 451 ((ipcp->cfg.vj.slots - 1) << 8) + 452 ipcp->cfg.vj.slotcomp; 453 else 454 ipcp->my_compproto = 0; 455 sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 456 457 ipcp->peer_reject = 0; 458 ipcp->my_reject = 0; 459 } 460 461 static int 462 ipcp_doproxyall(struct bundle *bundle, 463 int (*proxyfun)(struct bundle *, struct in_addr, int), int s) 464 { 465 int n, ret; 466 struct sticky_route *rp; 467 struct in_addr addr; 468 struct ipcp *ipcp; 469 470 ipcp = &bundle->ncp.ipcp; 471 for (rp = ipcp->route; rp != NULL; rp = rp->next) { 472 if (ntohl(rp->mask.s_addr) == INADDR_BROADCAST) 473 continue; 474 n = INADDR_BROADCAST - ntohl(rp->mask.s_addr) - 1; 475 if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) { 476 addr = rp->dst; 477 while (n--) { 478 addr.s_addr = htonl(ntohl(addr.s_addr) + 1); 479 log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr)); 480 ret = (*proxyfun)(bundle, addr, s); 481 if (!ret) 482 return ret; 483 } 484 } 485 } 486 487 return 0; 488 } 489 490 static int 491 ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 492 struct in_addr hisaddr, int silent) 493 { 494 static struct in_addr none = { INADDR_ANY }; 495 struct in_addr mask, oaddr; 496 u_int32_t addr; 497 498 addr = htonl(myaddr.s_addr); 499 if (IN_CLASSA(addr)) 500 mask.s_addr = htonl(IN_CLASSA_NET); 501 else if (IN_CLASSB(addr)) 502 mask.s_addr = htonl(IN_CLASSB_NET); 503 else 504 mask.s_addr = htonl(IN_CLASSC_NET); 505 506 if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY && 507 (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask.s_addr) == mask.s_addr) 508 mask.s_addr = htonl(bundle->ncp.ipcp.cfg.netmask.s_addr); 509 510 oaddr.s_addr = bundle->iface->in_addrs ? 511 bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY; 512 if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr, 513 IFACE_ADD_FIRST|IFACE_FORCE_ADD)) 514 return -1; 515 516 if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1 517 && myaddr.s_addr != oaddr.s_addr) 518 /* Nuke the old one */ 519 iface_inDelete(bundle->iface, oaddr); 520 521 if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0) 522 bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0); 523 524 if (Enabled(bundle, OPT_SROUTES)) 525 route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); 526 527 if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) { 528 int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 529 if (s < 0) 530 log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n", 531 strerror(errno)); 532 else { 533 if (Enabled(bundle, OPT_PROXYALL)) 534 ipcp_doproxyall(bundle, arp_SetProxy, s); 535 else if (Enabled(bundle, OPT_PROXY)) 536 arp_SetProxy(bundle, hisaddr, s); 537 close(s); 538 } 539 } 540 541 return 0; 542 } 543 544 static struct in_addr 545 ChooseHisAddr(struct bundle *bundle, struct in_addr gw) 546 { 547 struct in_addr try; 548 u_long f; 549 550 for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 551 try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 552 log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 553 f, inet_ntoa(try)); 554 if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 555 log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 556 break; 557 } 558 } 559 560 if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 561 log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 562 try.s_addr = INADDR_ANY; 563 } 564 565 return try; 566 } 567 568 static void 569 IpcpInitRestartCounter(struct fsm * fp) 570 { 571 /* Set fsm timer load */ 572 struct ipcp *ipcp = fsm2ipcp(fp); 573 574 fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS; 575 fp->restart = DEF_REQs; 576 } 577 578 static void 579 IpcpSendConfigReq(struct fsm *fp) 580 { 581 /* Send config REQ please */ 582 struct physical *p = link2physical(fp->link); 583 struct ipcp *ipcp = fsm2ipcp(fp); 584 u_char buff[24]; 585 struct lcp_opt *o; 586 587 o = (struct lcp_opt *)buff; 588 589 if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 590 memcpy(o->data, &ipcp->my_ip.s_addr, 4); 591 INC_LCP_OPT(TY_IPADDR, 6, o); 592 } 593 594 if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 595 if (ipcp->heis1172) { 596 u_int16_t proto = PROTO_VJCOMP; 597 598 ua_htons(&proto, o->data); 599 INC_LCP_OPT(TY_COMPPROTO, 4, o); 600 } else { 601 ua_htonl(&ipcp->my_compproto, o->data); 602 INC_LCP_OPT(TY_COMPPROTO, 6, o); 603 } 604 } 605 606 if (IsEnabled(ipcp->cfg.ns.dns_neg) && 607 !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 608 !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 609 struct in_addr dns[2]; 610 getdns(ipcp, dns); 611 memcpy(o->data, &dns[0].s_addr, 4); 612 INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 613 memcpy(o->data, &dns[1].s_addr, 4); 614 INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 615 } 616 617 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 618 } 619 620 static void 621 IpcpSentTerminateReq(struct fsm * fp) 622 { 623 /* Term REQ just sent by FSM */ 624 } 625 626 static void 627 IpcpSendTerminateAck(struct fsm *fp, u_char id) 628 { 629 /* Send Term ACK please */ 630 fsm_Output(fp, CODE_TERMACK, id, NULL, 0); 631 } 632 633 static void 634 IpcpLayerStart(struct fsm *fp) 635 { 636 /* We're about to start up ! */ 637 struct ipcp *ipcp = fsm2ipcp(fp); 638 639 log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 640 throughput_start(&ipcp->throughput, "IPCP throughput", 641 Enabled(fp->bundle, OPT_THROUGHPUT)); 642 643 /* This is where we should be setting up the interface in AUTO mode */ 644 } 645 646 static void 647 IpcpLayerFinish(struct fsm *fp) 648 { 649 /* We're now down */ 650 struct ipcp *ipcp = fsm2ipcp(fp); 651 652 log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 653 throughput_stop(&ipcp->throughput); 654 throughput_log(&ipcp->throughput, LogIPCP, NULL); 655 } 656 657 void 658 ipcp_CleanInterface(struct ipcp *ipcp) 659 { 660 struct iface *iface = ipcp->fsm.bundle->iface; 661 662 route_Clean(ipcp->fsm.bundle, ipcp->route); 663 664 if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) || 665 Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) { 666 int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 667 if (s < 0) 668 log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", 669 strerror(errno)); 670 else { 671 if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL)) 672 ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s); 673 else if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 674 arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s); 675 close(s); 676 } 677 } 678 679 iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL); 680 } 681 682 static void 683 IpcpLayerDown(struct fsm *fp) 684 { 685 /* About to come down */ 686 struct ipcp *ipcp = fsm2ipcp(fp); 687 const char *s; 688 689 if (ipcp->fsm.bundle->iface->in_addrs) 690 s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa); 691 else 692 s = "Interface configuration error !"; 693 log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s); 694 695 /* 696 * XXX this stuff should really live in the FSM. Our config should 697 * associate executable sections in files with events. 698 */ 699 if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 700 if (bundle_GetLabel(fp->bundle)) { 701 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 702 LINKDOWNFILE, NULL, NULL) < 0) 703 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 704 } else 705 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 706 } 707 708 ipcp_Setup(ipcp); 709 } 710 711 int 712 ipcp_InterfaceUp(struct ipcp *ipcp) 713 { 714 if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 715 log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 716 return 0; 717 } 718 719 #ifndef NOALIAS 720 if (ipcp->fsm.bundle->AliasEnabled) 721 PacketAliasSetAddress(ipcp->my_ip); 722 #endif 723 724 return 1; 725 } 726 727 static int 728 IpcpLayerUp(struct fsm *fp) 729 { 730 /* We're now up */ 731 struct ipcp *ipcp = fsm2ipcp(fp); 732 char tbuff[16]; 733 734 log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 735 snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 736 log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 737 tbuff, inet_ntoa(ipcp->peer_ip)); 738 739 if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 740 sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 741 742 if (!ipcp_InterfaceUp(ipcp)) 743 return 0; 744 745 /* 746 * XXX this stuff should really live in the FSM. Our config should 747 * associate executable sections in files with events. 748 */ 749 if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 750 if (bundle_GetLabel(fp->bundle)) { 751 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 752 LINKUPFILE, NULL, NULL) < 0) 753 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 754 } else 755 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 756 } 757 758 log_DisplayPrompts(); 759 return 1; 760 } 761 762 static int 763 AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr) 764 { 765 /* Is the given IP in the given range ? */ 766 return (prange->ipaddr.s_addr & prange->mask.s_addr) == 767 (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 768 } 769 770 static void 771 IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 772 struct fsm_decode *dec) 773 { 774 /* Deal with incoming PROTO_IPCP */ 775 struct iface *iface = fp->bundle->iface; 776 struct ipcp *ipcp = fsm2ipcp(fp); 777 int type, length, gotdns, gotdnsnak, n; 778 u_int32_t compproto; 779 struct compreq *pcomp; 780 struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 781 char tbuff[100], tbuff2[100]; 782 783 gotdns = 0; 784 gotdnsnak = 0; 785 dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 786 787 while (plen >= sizeof(struct fsmconfig)) { 788 type = *cp; 789 length = cp[1]; 790 791 if (length == 0) { 792 log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 793 break; 794 } 795 796 if (type < NCFTYPES) 797 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 798 else if (type > 128 && type < 128 + NCFTYPES128) 799 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 800 else 801 snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 802 803 switch (type) { 804 case TY_IPADDR: /* RFC1332 */ 805 memcpy(&ipaddr.s_addr, cp + 2, 4); 806 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 807 808 switch (mode_type) { 809 case MODE_REQ: 810 if (iplist_isvalid(&ipcp->cfg.peer_list)) { 811 if (ipaddr.s_addr == INADDR_ANY || 812 iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 813 ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 814 ipaddr, 1)) { 815 log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 816 inet_ntoa(ipaddr)); 817 /* 818 * If we've already had a valid address configured for the peer, 819 * try NAKing with that so that we don't have to upset things 820 * too much. 821 */ 822 for (n = 0; n < iface->in_addrs; n++) 823 if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) 824 >=0) { 825 ipcp->peer_ip = iface->in_addr[n].brd; 826 break; 827 } 828 829 if (n == iface->in_addrs) 830 /* Just pick an IP number from our list */ 831 ipcp->peer_ip = ChooseHisAddr 832 (fp->bundle, ipcp->cfg.my_range.ipaddr); 833 834 if (ipcp->peer_ip.s_addr == INADDR_ANY) { 835 memcpy(dec->rejend, cp, length); 836 dec->rejend += length; 837 } else { 838 memcpy(dec->nakend, cp, 2); 839 memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 840 dec->nakend += length; 841 } 842 break; 843 } 844 } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 845 /* 846 * If destination address is not acceptable, NAK with what we 847 * want to use. 848 */ 849 memcpy(dec->nakend, cp, 2); 850 for (n = 0; n < iface->in_addrs; n++) 851 if ((iface->in_addr[n].brd.s_addr & 852 ipcp->cfg.peer_range.mask.s_addr) 853 == (ipcp->cfg.peer_range.ipaddr.s_addr & 854 ipcp->cfg.peer_range.mask.s_addr)) { 855 /* We prefer the already-configured address */ 856 memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr, 857 length - 2); 858 break; 859 } 860 861 if (n == iface->in_addrs) 862 memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 863 864 dec->nakend += length; 865 break; 866 } 867 ipcp->peer_ip = ipaddr; 868 memcpy(dec->ackend, cp, length); 869 dec->ackend += length; 870 break; 871 872 case MODE_NAK: 873 if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 874 /* Use address suggested by peer */ 875 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 876 inet_ntoa(ipcp->my_ip)); 877 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 878 ipcp->my_ip = ipaddr; 879 } else { 880 log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 881 "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 882 fsm_Close(&ipcp->fsm); 883 } 884 break; 885 886 case MODE_REJ: 887 ipcp->peer_reject |= (1 << type); 888 break; 889 } 890 break; 891 892 case TY_COMPPROTO: 893 memcpy(&compproto, cp + 2, 4); 894 log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 895 896 switch (mode_type) { 897 case MODE_REQ: 898 if (!IsAccepted(ipcp->cfg.vj.neg)) { 899 memcpy(dec->rejend, cp, length); 900 dec->rejend += length; 901 } else { 902 pcomp = (struct compreq *) (cp + 2); 903 switch (length) { 904 case 4: /* RFC1172 */ 905 if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 906 log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 907 ipcp->heis1172 = 1; 908 ipcp->peer_compproto = compproto; 909 memcpy(dec->ackend, cp, length); 910 dec->ackend += length; 911 } else { 912 memcpy(dec->nakend, cp, 2); 913 pcomp->proto = htons(PROTO_VJCOMP); 914 memcpy(dec->nakend+2, &pcomp, 2); 915 dec->nakend += length; 916 } 917 break; 918 case 6: /* RFC1332 */ 919 if (ntohs(pcomp->proto) == PROTO_VJCOMP 920 && pcomp->slots <= MAX_VJ_STATES 921 && pcomp->slots >= MIN_VJ_STATES) { 922 ipcp->peer_compproto = compproto; 923 ipcp->heis1172 = 0; 924 memcpy(dec->ackend, cp, length); 925 dec->ackend += length; 926 } else { 927 memcpy(dec->nakend, cp, 2); 928 pcomp->proto = htons(PROTO_VJCOMP); 929 pcomp->slots = DEF_VJ_STATES; 930 pcomp->compcid = 0; 931 memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 932 dec->nakend += length; 933 } 934 break; 935 default: 936 memcpy(dec->rejend, cp, length); 937 dec->rejend += length; 938 break; 939 } 940 } 941 break; 942 943 case MODE_NAK: 944 log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 945 tbuff, ipcp->my_compproto, compproto); 946 ipcp->my_compproto = compproto; 947 break; 948 949 case MODE_REJ: 950 ipcp->peer_reject |= (1 << type); 951 break; 952 } 953 break; 954 955 case TY_IPADDRS: /* RFC1172 */ 956 memcpy(&ipaddr.s_addr, cp + 2, 4); 957 memcpy(&dstipaddr.s_addr, cp + 6, 4); 958 snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 959 log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 960 961 switch (mode_type) { 962 case MODE_REQ: 963 ipcp->peer_ip = ipaddr; 964 ipcp->my_ip = dstipaddr; 965 memcpy(dec->ackend, cp, length); 966 dec->ackend += length; 967 break; 968 969 case MODE_NAK: 970 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 971 inet_ntoa(ipcp->my_ip)); 972 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 973 ipcp->my_ip = ipaddr; 974 ipcp->peer_ip = dstipaddr; 975 break; 976 977 case MODE_REJ: 978 ipcp->peer_reject |= (1 << type); 979 break; 980 } 981 break; 982 983 case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 984 case TY_SECONDARY_DNS: 985 memcpy(&ipaddr.s_addr, cp + 2, 4); 986 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 987 988 switch (mode_type) { 989 case MODE_REQ: 990 if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 991 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 992 memcpy(dec->rejend, cp, length); 993 dec->rejend += length; 994 break; 995 } 996 if (!gotdns) { 997 dns[0] = ipcp->cfg.ns.dns[0]; 998 dns[1] = ipcp->cfg.ns.dns[1]; 999 if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 1000 getdns(ipcp, dns); 1001 gotdns = 1; 1002 } 1003 have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 1004 1005 if (ipaddr.s_addr != have_ip.s_addr) { 1006 /* 1007 * The client has got the DNS stuff wrong (first request) so 1008 * we'll tell 'em how it is 1009 */ 1010 memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 1011 memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 1012 dec->nakend += length; 1013 } else { 1014 /* 1015 * Otherwise they have it right (this time) so we send a ack packet 1016 * back confirming it... end of story 1017 */ 1018 memcpy(dec->ackend, cp, length); 1019 dec->ackend += length; 1020 } 1021 break; 1022 1023 case MODE_NAK: /* what does this mean?? */ 1024 if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 1025 gotdnsnak = 1; 1026 memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); 1027 } 1028 break; 1029 1030 case MODE_REJ: /* Can't do much, stop asking */ 1031 ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 1032 break; 1033 } 1034 break; 1035 1036 case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1037 case TY_SECONDARY_NBNS: 1038 memcpy(&ipaddr.s_addr, cp + 2, 4); 1039 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 1040 1041 switch (mode_type) { 1042 case MODE_REQ: 1043 have_ip.s_addr = 1044 ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 1045 1046 if (have_ip.s_addr == INADDR_ANY) { 1047 log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 1048 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 1049 memcpy(dec->rejend, cp, length); 1050 dec->rejend += length; 1051 break; 1052 } 1053 1054 if (ipaddr.s_addr != have_ip.s_addr) { 1055 memcpy(dec->nakend, cp, 2); 1056 memcpy(dec->nakend+2, &have_ip.s_addr, length); 1057 dec->nakend += length; 1058 } else { 1059 memcpy(dec->ackend, cp, length); 1060 dec->ackend += length; 1061 } 1062 break; 1063 1064 case MODE_NAK: 1065 log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 1066 break; 1067 1068 case MODE_REJ: 1069 log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 1070 break; 1071 } 1072 break; 1073 1074 default: 1075 if (mode_type != MODE_NOP) { 1076 ipcp->my_reject |= (1 << type); 1077 memcpy(dec->rejend, cp, length); 1078 dec->rejend += length; 1079 } 1080 break; 1081 } 1082 plen -= length; 1083 cp += length; 1084 } 1085 1086 if (gotdnsnak) 1087 if (!setdns(ipcp, dnsnak)) { 1088 ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 1089 ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 1090 } 1091 1092 if (mode_type != MODE_NOP) { 1093 if (dec->rejend != dec->rej) { 1094 /* rejects are preferred */ 1095 dec->ackend = dec->ack; 1096 dec->nakend = dec->nak; 1097 } else if (dec->nakend != dec->nak) 1098 /* then NAKs */ 1099 dec->ackend = dec->ack; 1100 } 1101 } 1102 1103 void 1104 ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp) 1105 { 1106 /* Got PROTO_IPCP from link */ 1107 if (bundle_Phase(bundle) == PHASE_NETWORK) 1108 fsm_Input(&ipcp->fsm, bp); 1109 else { 1110 if (bundle_Phase(bundle) < PHASE_NETWORK) 1111 log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 1112 ipcp->fsm.link->name, bundle_PhaseName(bundle)); 1113 mbuf_Free(bp); 1114 } 1115 } 1116 1117 int 1118 ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 1119 { 1120 struct ipcp *ipcp = &bundle->ncp.ipcp; 1121 1122 /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 1123 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1124 iplist_reset(&ipcp->cfg.peer_list); 1125 if (strpbrk(hisaddr, ",-")) { 1126 iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 1127 if (iplist_isvalid(&ipcp->cfg.peer_list)) { 1128 iplist_setrandpos(&ipcp->cfg.peer_list); 1129 ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 1130 if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1131 log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 1132 return(0); 1133 } 1134 ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 1135 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 1136 ipcp->cfg.peer_range.width = 32; 1137 } else { 1138 log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 1139 return 0; 1140 } 1141 } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 1142 &ipcp->cfg.peer_range.mask, 1143 &ipcp->cfg.peer_range.width) != 0) { 1144 ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 1145 1146 if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 1147 ipcp->cfg.peer_range.ipaddr, 0) < 0) 1148 return 0; 1149 } else 1150 return 0; 1151 1152 return 1; 1153 } 1154