1 /* $NetBSD: ipcp.c,v 1.4 2014/10/25 21:11:37 christos Exp $ */ 2 3 /* 4 * ipcp.c - PPP IP Control Protocol. 5 * 6 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. The name "Carnegie Mellon University" must not be used to 21 * endorse or promote products derived from this software without 22 * prior written permission. For permission or any legal 23 * details, please contact 24 * Office of Technology Transfer 25 * Carnegie Mellon University 26 * 5000 Forbes Avenue 27 * Pittsburgh, PA 15213-3890 28 * (412) 268-4387, fax: (412) 268-7395 29 * tech-transfer@andrew.cmu.edu 30 * 31 * 4. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by Computing Services 34 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 35 * 36 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 37 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 38 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 39 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 40 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 41 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 42 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 43 */ 44 45 #include <sys/cdefs.h> 46 #if 0 47 #define RCSID "Id: ipcp.c,v 1.73 2008/05/26 08:33:22 paulus Exp " 48 static const char rcsid[] = RCSID; 49 #else 50 __RCSID("$NetBSD: ipcp.c,v 1.4 2014/10/25 21:11:37 christos Exp $"); 51 #endif 52 53 /* 54 * TODO: 55 */ 56 57 #include <stdio.h> 58 #include <string.h> 59 #include <stdlib.h> 60 #include <netdb.h> 61 #include <sys/param.h> 62 #include <sys/types.h> 63 #include <sys/socket.h> 64 #include <netinet/in.h> 65 #include <arpa/inet.h> 66 67 #include "pppd.h" 68 #include "fsm.h" 69 #include "ipcp.h" 70 #include "pathnames.h" 71 72 73 /* global vars */ 74 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ 75 ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ 76 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ 77 ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ 78 79 u_int32_t netmask = 0; /* IP netmask to set on interface */ 80 81 bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ 82 bool noremoteip = 0; /* Let him have no IP address */ 83 84 /* Hook for a plugin to know when IP protocol has come up */ 85 void (*ip_up_hook) __P((void)) = NULL; 86 87 /* Hook for a plugin to know when IP protocol has come down */ 88 void (*ip_down_hook) __P((void)) = NULL; 89 90 /* Hook for a plugin to choose the remote IP address */ 91 void (*ip_choose_hook) __P((u_int32_t *)) = NULL; 92 93 /* Notifiers for when IPCP goes up and down */ 94 struct notifier *ip_up_notifier = NULL; 95 struct notifier *ip_down_notifier = NULL; 96 97 /* local vars */ 98 static int default_route_set[NUM_PPP]; /* Have set up a default route */ 99 static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ 100 static bool usepeerdns; /* Ask peer for DNS addrs */ 101 static int ipcp_is_up; /* have called np_up() */ 102 static int ipcp_is_open; /* haven't called np_finished() */ 103 static bool ask_for_local; /* request our address from peer */ 104 static char vj_value[8]; /* string form of vj option value */ 105 static char netmask_str[20]; /* string form of netmask value */ 106 107 /* 108 * Callbacks for fsm code. (CI = Configuration Information) 109 */ 110 static void ipcp_resetci __P((fsm *)); /* Reset our CI */ 111 static int ipcp_cilen __P((fsm *)); /* Return length of our CI */ 112 static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */ 113 static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ 114 static int ipcp_nakci __P((fsm *, u_char *, int, int));/* Peer nak'd our CI */ 115 static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ 116 static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ 117 static void ipcp_up __P((fsm *)); /* We're UP */ 118 static void ipcp_down __P((fsm *)); /* We're DOWN */ 119 static void ipcp_finished __P((fsm *)); /* Don't need lower layer */ 120 121 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ 122 123 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ 124 ipcp_resetci, /* Reset our Configuration Information */ 125 ipcp_cilen, /* Length of our Configuration Information */ 126 ipcp_addci, /* Add our Configuration Information */ 127 ipcp_ackci, /* ACK our Configuration Information */ 128 ipcp_nakci, /* NAK our Configuration Information */ 129 ipcp_rejci, /* Reject our Configuration Information */ 130 ipcp_reqci, /* Request peer's Configuration Information */ 131 ipcp_up, /* Called when fsm reaches OPENED state */ 132 ipcp_down, /* Called when fsm leaves OPENED state */ 133 NULL, /* Called when we want the lower layer up */ 134 ipcp_finished, /* Called when we want the lower layer down */ 135 NULL, /* Called when Protocol-Reject received */ 136 NULL, /* Retransmission is necessary */ 137 NULL, /* Called to handle protocol-specific codes */ 138 "IPCP" /* String name of protocol */ 139 }; 140 141 /* 142 * Command-line options. 143 */ 144 static int setvjslots __P((char **)); 145 static int setdnsaddr __P((char **)); 146 static int setwinsaddr __P((char **)); 147 static int setnetmask __P((char **)); 148 int setipaddr __P((char *, char **, int)); 149 static void printipaddr __P((option_t *, void (*)(void *, char *,...),void *)); 150 151 static option_t ipcp_option_list[] = { 152 { "noip", o_bool, &ipcp_protent.enabled_flag, 153 "Disable IP and IPCP" }, 154 { "-ip", o_bool, &ipcp_protent.enabled_flag, 155 "Disable IP and IPCP", OPT_ALIAS }, 156 157 { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, 158 "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, 159 { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, 160 "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, 161 &ipcp_allowoptions[0].neg_vj }, 162 163 { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, 164 "Disable VJ connection-ID compression", OPT_A2CLR, 165 &ipcp_allowoptions[0].cflag }, 166 { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, 167 "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, 168 &ipcp_allowoptions[0].cflag }, 169 170 { "vj-max-slots", o_special, (void *)setvjslots, 171 "Set maximum VJ header slots", 172 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, 173 174 { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, 175 "Accept peer's address for us", 1 }, 176 { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, 177 "Accept peer's address for it", 1 }, 178 179 { "ipparam", o_string, &ipparam, 180 "Set ip script parameter", OPT_PRIO }, 181 182 { "noipdefault", o_bool, &disable_defaultip, 183 "Don't use name for default IP adrs", 1 }, 184 185 { "ms-dns", 1, (void *)setdnsaddr, 186 "DNS address for the peer's use" }, 187 { "ms-wins", 1, (void *)setwinsaddr, 188 "Nameserver for SMB over TCP/IP for peer" }, 189 190 { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, 191 "Set timeout for IPCP", OPT_PRIO }, 192 { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, 193 "Set max #xmits for term-reqs", OPT_PRIO }, 194 { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, 195 "Set max #xmits for conf-reqs", OPT_PRIO }, 196 { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, 197 "Set max #conf-naks for IPCP", OPT_PRIO }, 198 199 { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, 200 "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, 201 { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, 202 "disable defaultroute option", OPT_A2CLR, 203 &ipcp_wantoptions[0].default_route }, 204 { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, 205 "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, 206 &ipcp_wantoptions[0].default_route }, 207 208 { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, 209 "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, 210 { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, 211 "disable proxyarp option", OPT_A2CLR, 212 &ipcp_wantoptions[0].proxy_arp }, 213 { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, 214 "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, 215 &ipcp_wantoptions[0].proxy_arp }, 216 217 { "usepeerdns", o_bool, &usepeerdns, 218 "Ask peer for DNS address(es)", 1 }, 219 220 { "netmask", o_special, (void *)setnetmask, 221 "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, 222 223 { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs, 224 "Disable old-style IP-Addresses usage", OPT_A2CLR, 225 &ipcp_allowoptions[0].old_addrs }, 226 { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr, 227 "Disable IP-Address usage", OPT_A2CLR, 228 &ipcp_allowoptions[0].neg_addr }, 229 #ifdef __linux__ 230 { "noremoteip", o_bool, &noremoteip, 231 "Allow peer to have no IP address", 1 }, 232 #endif 233 { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr, 234 "Don't send our IP address to peer", OPT_A2CLR, 235 &ipcp_wantoptions[0].old_addrs}, 236 237 { "IP addresses", o_wild, (void *) &setipaddr, 238 "set local and remote IP addresses", 239 OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, 240 241 { NULL } 242 }; 243 244 /* 245 * Protocol entry points from main code. 246 */ 247 static void ipcp_init __P((int)); 248 static void ipcp_open __P((int)); 249 static void ipcp_close __P((int, char *)); 250 static void ipcp_lowerup __P((int)); 251 static void ipcp_lowerdown __P((int)); 252 static void ipcp_input __P((int, u_char *, int)); 253 static void ipcp_protrej __P((int)); 254 static int ipcp_printpkt __P((u_char *, int, 255 void (*) __P((void *, char *, ...)), void *)); 256 static void ip_check_options __P((void)); 257 static int ip_demand_conf __P((int)); 258 static int ip_active_pkt __P((u_char *, int)); 259 static void create_resolv __P((u_int32_t, u_int32_t)); 260 261 struct protent ipcp_protent = { 262 PPP_IPCP, 263 ipcp_init, 264 ipcp_input, 265 ipcp_protrej, 266 ipcp_lowerup, 267 ipcp_lowerdown, 268 ipcp_open, 269 ipcp_close, 270 ipcp_printpkt, 271 NULL, 272 1, 273 "IPCP", 274 "IP", 275 ipcp_option_list, 276 ip_check_options, 277 ip_demand_conf, 278 ip_active_pkt 279 }; 280 281 static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t)); 282 static void ipcp_script __P((char *, int)); /* Run an up/down script */ 283 static void ipcp_script_done __P((void *)); 284 285 /* 286 * Lengths of configuration options. 287 */ 288 #define CILEN_VOID 2 289 #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ 290 #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ 291 #define CILEN_ADDR 6 /* new-style single address option */ 292 #define CILEN_ADDRS 10 /* old-style dual address option */ 293 294 295 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ 296 (x) == CONFNAK ? "NAK" : "REJ") 297 298 /* 299 * This state variable is used to ensure that we don't 300 * run an ipcp-up/down script while one is already running. 301 */ 302 static enum script_state { 303 s_down, 304 s_up, 305 } ipcp_script_state; 306 static pid_t ipcp_script_pid; 307 308 /* 309 * Make a string representation of a network IP address. 310 */ 311 char * 312 ip_ntoa(ipaddr) 313 u_int32_t ipaddr; 314 { 315 static char b[64]; 316 317 slprintf(b, sizeof(b), "%I", ipaddr); 318 return b; 319 } 320 321 /* 322 * Option parsing. 323 */ 324 325 /* 326 * setvjslots - set maximum number of connection slots for VJ compression 327 */ 328 static int 329 setvjslots(argv) 330 char **argv; 331 { 332 int value; 333 334 if (!int_option(*argv, &value)) 335 return 0; 336 if (value < 2 || value > 16) { 337 option_error("vj-max-slots value must be between 2 and 16"); 338 return 0; 339 } 340 ipcp_wantoptions [0].maxslotindex = 341 ipcp_allowoptions[0].maxslotindex = value - 1; 342 slprintf(vj_value, sizeof(vj_value), "%d", value); 343 return 1; 344 } 345 346 /* 347 * setdnsaddr - set the dns address(es) 348 */ 349 static int 350 setdnsaddr(argv) 351 char **argv; 352 { 353 u_int32_t dns; 354 struct hostent *hp; 355 356 dns = inet_addr(*argv); 357 if (dns == (u_int32_t) -1) { 358 if ((hp = gethostbyname(*argv)) == NULL) { 359 option_error("invalid address parameter '%s' for ms-dns option", 360 *argv); 361 return 0; 362 } 363 dns = *(u_int32_t *)hp->h_addr; 364 } 365 366 /* We take the last 2 values given, the 2nd-last as the primary 367 and the last as the secondary. If only one is given it 368 becomes both primary and secondary. */ 369 if (ipcp_allowoptions[0].dnsaddr[1] == 0) 370 ipcp_allowoptions[0].dnsaddr[0] = dns; 371 else 372 ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; 373 374 /* always set the secondary address value. */ 375 ipcp_allowoptions[0].dnsaddr[1] = dns; 376 377 return (1); 378 } 379 380 /* 381 * setwinsaddr - set the wins address(es) 382 * This is primrarly used with the Samba package under UNIX or for pointing 383 * the caller to the existing WINS server on a Windows NT platform. 384 */ 385 static int 386 setwinsaddr(argv) 387 char **argv; 388 { 389 u_int32_t wins; 390 struct hostent *hp; 391 392 wins = inet_addr(*argv); 393 if (wins == (u_int32_t) -1) { 394 if ((hp = gethostbyname(*argv)) == NULL) { 395 option_error("invalid address parameter '%s' for ms-wins option", 396 *argv); 397 return 0; 398 } 399 wins = *(u_int32_t *)hp->h_addr; 400 } 401 402 /* We take the last 2 values given, the 2nd-last as the primary 403 and the last as the secondary. If only one is given it 404 becomes both primary and secondary. */ 405 if (ipcp_allowoptions[0].winsaddr[1] == 0) 406 ipcp_allowoptions[0].winsaddr[0] = wins; 407 else 408 ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; 409 410 /* always set the secondary address value. */ 411 ipcp_allowoptions[0].winsaddr[1] = wins; 412 413 return (1); 414 } 415 416 /* 417 * setipaddr - Set the IP address 418 * If doit is 0, the call is to check whether this option is 419 * potentially an IP address specification. 420 * Not static so that plugins can call it to set the addresses 421 */ 422 int 423 setipaddr(arg, argv, doit) 424 char *arg; 425 char **argv; 426 int doit; 427 { 428 struct hostent *hp; 429 char *colon; 430 u_int32_t local, remote; 431 ipcp_options *wo = &ipcp_wantoptions[0]; 432 static int prio_local = 0, prio_remote = 0; 433 434 /* 435 * IP address pair separated by ":". 436 */ 437 if ((colon = strchr(arg, ':')) == NULL) 438 return 0; 439 if (!doit) 440 return 1; 441 442 /* 443 * If colon first character, then no local addr. 444 */ 445 if (colon != arg && option_priority >= prio_local) { 446 *colon = '\0'; 447 if ((local = inet_addr(arg)) == (u_int32_t) -1) { 448 if ((hp = gethostbyname(arg)) == NULL) { 449 option_error("unknown host: %s", arg); 450 return 0; 451 } 452 local = *(u_int32_t *)hp->h_addr; 453 } 454 if (bad_ip_adrs(local)) { 455 option_error("bad local IP address %s", ip_ntoa(local)); 456 return 0; 457 } 458 if (local != 0) 459 wo->ouraddr = local; 460 *colon = ':'; 461 prio_local = option_priority; 462 } 463 464 /* 465 * If colon last character, then no remote addr. 466 */ 467 if (*++colon != '\0' && option_priority >= prio_remote) { 468 if ((remote = inet_addr(colon)) == (u_int32_t) -1) { 469 if ((hp = gethostbyname(colon)) == NULL) { 470 option_error("unknown host: %s", colon); 471 return 0; 472 } 473 remote = *(u_int32_t *)hp->h_addr; 474 if (remote_name[0] == 0) 475 strlcpy(remote_name, colon, sizeof(remote_name)); 476 } 477 if (bad_ip_adrs(remote)) { 478 option_error("bad remote IP address %s", ip_ntoa(remote)); 479 return 0; 480 } 481 if (remote != 0) 482 wo->hisaddr = remote; 483 prio_remote = option_priority; 484 } 485 486 return 1; 487 } 488 489 static void 490 printipaddr(opt, printer, arg) 491 option_t *opt; 492 void (*printer) __P((void *, char *, ...)); 493 void *arg; 494 { 495 ipcp_options *wo = &ipcp_wantoptions[0]; 496 497 if (wo->ouraddr != 0) 498 printer(arg, "%I", wo->ouraddr); 499 printer(arg, ":"); 500 if (wo->hisaddr != 0) 501 printer(arg, "%I", wo->hisaddr); 502 } 503 504 /* 505 * setnetmask - set the netmask to be used on the interface. 506 */ 507 static int 508 setnetmask(argv) 509 char **argv; 510 { 511 u_int32_t mask; 512 int n; 513 char *p; 514 515 /* 516 * Unfortunately, if we use inet_addr, we can't tell whether 517 * a result of all 1s is an error or a valid 255.255.255.255. 518 */ 519 p = *argv; 520 n = parse_dotted_ip(p, &mask); 521 522 mask = htonl(mask); 523 524 if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { 525 option_error("invalid netmask value '%s'", *argv); 526 return 0; 527 } 528 529 netmask = mask; 530 slprintf(netmask_str, sizeof(netmask_str), "%I", mask); 531 532 return (1); 533 } 534 535 int 536 parse_dotted_ip(p, vp) 537 char *p; 538 u_int32_t *vp; 539 { 540 int n; 541 u_int32_t v, b; 542 char *endp, *p0 = p; 543 544 v = 0; 545 for (n = 3;; --n) { 546 b = strtoul(p, &endp, 0); 547 if (endp == p) 548 return 0; 549 if (b > 255) { 550 if (n < 3) 551 return 0; 552 /* accept e.g. 0xffffff00 */ 553 *vp = b; 554 return endp - p0; 555 } 556 v |= b << (n * 8); 557 p = endp; 558 if (n == 0) 559 break; 560 if (*p != '.') 561 return 0; 562 ++p; 563 } 564 *vp = v; 565 return p - p0; 566 } 567 568 569 /* 570 * ipcp_init - Initialize IPCP. 571 */ 572 static void 573 ipcp_init(unit) 574 int unit; 575 { 576 fsm *f = &ipcp_fsm[unit]; 577 ipcp_options *wo = &ipcp_wantoptions[unit]; 578 ipcp_options *ao = &ipcp_allowoptions[unit]; 579 580 f->unit = unit; 581 f->protocol = PPP_IPCP; 582 f->callbacks = &ipcp_callbacks; 583 fsm_init(&ipcp_fsm[unit]); 584 585 /* 586 * Some 3G modems use repeated IPCP NAKs as a way of stalling 587 * until they can contact a server on the network, so we increase 588 * the default number of NAKs we accept before we start treating 589 * them as rejects. 590 */ 591 f->maxnakloops = 100; 592 593 memset(wo, 0, sizeof(*wo)); 594 memset(ao, 0, sizeof(*ao)); 595 596 wo->neg_addr = wo->old_addrs = 1; 597 wo->neg_vj = 1; 598 wo->vj_protocol = IPCP_VJ_COMP; 599 wo->maxslotindex = MAX_STATES - 1; /* really max index */ 600 wo->cflag = 1; 601 602 603 /* max slots and slot-id compression are currently hardwired in */ 604 /* ppp_if.c to 16 and 1, this needs to be changed (among other */ 605 /* things) gmc */ 606 607 ao->neg_addr = ao->old_addrs = 1; 608 ao->neg_vj = 1; 609 ao->maxslotindex = MAX_STATES - 1; 610 ao->cflag = 1; 611 612 /* 613 * XXX These control whether the user may use the proxyarp 614 * and defaultroute options. 615 */ 616 ao->proxy_arp = 1; 617 ao->default_route = 1; 618 } 619 620 621 /* 622 * ipcp_open - IPCP is allowed to come up. 623 */ 624 static void 625 ipcp_open(unit) 626 int unit; 627 { 628 fsm_open(&ipcp_fsm[unit]); 629 ipcp_is_open = 1; 630 } 631 632 633 /* 634 * ipcp_close - Take IPCP down. 635 */ 636 static void 637 ipcp_close(unit, reason) 638 int unit; 639 char *reason; 640 { 641 fsm_close(&ipcp_fsm[unit], reason); 642 } 643 644 645 /* 646 * ipcp_lowerup - The lower layer is up. 647 */ 648 static void 649 ipcp_lowerup(unit) 650 int unit; 651 { 652 fsm_lowerup(&ipcp_fsm[unit]); 653 } 654 655 656 /* 657 * ipcp_lowerdown - The lower layer is down. 658 */ 659 static void 660 ipcp_lowerdown(unit) 661 int unit; 662 { 663 fsm_lowerdown(&ipcp_fsm[unit]); 664 } 665 666 667 /* 668 * ipcp_input - Input IPCP packet. 669 */ 670 static void 671 ipcp_input(unit, p, len) 672 int unit; 673 u_char *p; 674 int len; 675 { 676 fsm_input(&ipcp_fsm[unit], p, len); 677 } 678 679 680 /* 681 * ipcp_protrej - A Protocol-Reject was received for IPCP. 682 * 683 * Pretend the lower layer went down, so we shut up. 684 */ 685 static void 686 ipcp_protrej(unit) 687 int unit; 688 { 689 fsm_lowerdown(&ipcp_fsm[unit]); 690 } 691 692 693 /* 694 * ipcp_resetci - Reset our CI. 695 * Called by fsm_sconfreq, Send Configure Request. 696 */ 697 static void 698 ipcp_resetci(f) 699 fsm *f; 700 { 701 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 702 ipcp_options *go = &ipcp_gotoptions[f->unit]; 703 ipcp_options *ao = &ipcp_allowoptions[f->unit]; 704 705 wo->req_addr = (wo->neg_addr || wo->old_addrs) && 706 (ao->neg_addr || ao->old_addrs); 707 if (wo->ouraddr == 0) 708 wo->accept_local = 1; 709 if (wo->hisaddr == 0) 710 wo->accept_remote = 1; 711 wo->req_dns1 = usepeerdns; /* Request DNS addresses from the peer */ 712 wo->req_dns2 = usepeerdns; 713 *go = *wo; 714 if (!ask_for_local) 715 go->ouraddr = 0; 716 if (ip_choose_hook) { 717 ip_choose_hook(&wo->hisaddr); 718 if (wo->hisaddr) { 719 wo->accept_remote = 0; 720 } 721 } 722 BZERO(&ipcp_hisoptions[f->unit], sizeof(ipcp_options)); 723 } 724 725 726 /* 727 * ipcp_cilen - Return length of our CI. 728 * Called by fsm_sconfreq, Send Configure Request. 729 */ 730 static int 731 ipcp_cilen(f) 732 fsm *f; 733 { 734 ipcp_options *go = &ipcp_gotoptions[f->unit]; 735 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 736 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 737 738 #define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) 739 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) 740 #define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) 741 #define LENCIDNS(neg) LENCIADDR(neg) 742 #define LENCIWINS(neg) LENCIADDR(neg) 743 744 /* 745 * First see if we want to change our options to the old 746 * forms because we have received old forms from the peer. 747 */ 748 if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) 749 go->neg_addr = 0; 750 if (wo->neg_vj && !go->neg_vj && !go->old_vj) { 751 /* try an older style of VJ negotiation */ 752 /* use the old style only if the peer did */ 753 if (ho->neg_vj && ho->old_vj) { 754 go->neg_vj = 1; 755 go->old_vj = 1; 756 go->vj_protocol = ho->vj_protocol; 757 } 758 } 759 760 return (LENCIADDRS(!go->neg_addr && go->old_addrs) + 761 LENCIVJ(go->neg_vj, go->old_vj) + 762 LENCIADDR(go->neg_addr) + 763 LENCIDNS(go->req_dns1) + 764 LENCIDNS(go->req_dns2) + 765 LENCIWINS(go->winsaddr[0]) + 766 LENCIWINS(go->winsaddr[1])) ; 767 } 768 769 770 /* 771 * ipcp_addci - Add our desired CIs to a packet. 772 * Called by fsm_sconfreq, Send Configure Request. 773 */ 774 static void 775 ipcp_addci(f, ucp, lenp) 776 fsm *f; 777 u_char *ucp; 778 int *lenp; 779 { 780 ipcp_options *go = &ipcp_gotoptions[f->unit]; 781 int len = *lenp; 782 783 #define ADDCIADDRS(opt, neg, val1, val2) \ 784 if (neg) { \ 785 if (len >= CILEN_ADDRS) { \ 786 u_int32_t l; \ 787 PUTCHAR(opt, ucp); \ 788 PUTCHAR(CILEN_ADDRS, ucp); \ 789 l = ntohl(val1); \ 790 PUTLONG(l, ucp); \ 791 l = ntohl(val2); \ 792 PUTLONG(l, ucp); \ 793 len -= CILEN_ADDRS; \ 794 } else \ 795 go->old_addrs = 0; \ 796 } 797 798 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 799 if (neg) { \ 800 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 801 if (len >= vjlen) { \ 802 PUTCHAR(opt, ucp); \ 803 PUTCHAR(vjlen, ucp); \ 804 PUTSHORT(val, ucp); \ 805 if (!old) { \ 806 PUTCHAR(maxslotindex, ucp); \ 807 PUTCHAR(cflag, ucp); \ 808 } \ 809 len -= vjlen; \ 810 } else \ 811 neg = 0; \ 812 } 813 814 #define ADDCIADDR(opt, neg, val) \ 815 if (neg) { \ 816 if (len >= CILEN_ADDR) { \ 817 u_int32_t l; \ 818 PUTCHAR(opt, ucp); \ 819 PUTCHAR(CILEN_ADDR, ucp); \ 820 l = ntohl(val); \ 821 PUTLONG(l, ucp); \ 822 len -= CILEN_ADDR; \ 823 } else \ 824 neg = 0; \ 825 } 826 827 #define ADDCIDNS(opt, neg, addr) \ 828 if (neg) { \ 829 if (len >= CILEN_ADDR) { \ 830 u_int32_t l; \ 831 PUTCHAR(opt, ucp); \ 832 PUTCHAR(CILEN_ADDR, ucp); \ 833 l = ntohl(addr); \ 834 PUTLONG(l, ucp); \ 835 len -= CILEN_ADDR; \ 836 } else \ 837 neg = 0; \ 838 } 839 840 #define ADDCIWINS(opt, addr) \ 841 if (addr) { \ 842 if (len >= CILEN_ADDR) { \ 843 u_int32_t l; \ 844 PUTCHAR(opt, ucp); \ 845 PUTCHAR(CILEN_ADDR, ucp); \ 846 l = ntohl(addr); \ 847 PUTLONG(l, ucp); \ 848 len -= CILEN_ADDR; \ 849 } else \ 850 addr = 0; \ 851 } 852 853 ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, 854 go->hisaddr); 855 856 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 857 go->maxslotindex, go->cflag); 858 859 ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); 860 861 ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 862 863 ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 864 865 ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); 866 867 ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); 868 869 *lenp -= len; 870 } 871 872 873 /* 874 * ipcp_ackci - Ack our CIs. 875 * Called by fsm_rconfack, Receive Configure ACK. 876 * 877 * Returns: 878 * 0 - Ack was bad. 879 * 1 - Ack was good. 880 */ 881 static int 882 ipcp_ackci(f, p, len) 883 fsm *f; 884 u_char *p; 885 int len; 886 { 887 ipcp_options *go = &ipcp_gotoptions[f->unit]; 888 u_short cilen, citype, cishort; 889 u_int32_t cilong; 890 u_char cimaxslotindex, cicflag; 891 892 /* 893 * CIs must be in exactly the same order that we sent... 894 * Check packet length and CI length at each step. 895 * If we find any deviations, then this packet is bad. 896 */ 897 898 #define ACKCIADDRS(opt, neg, val1, val2) \ 899 if (neg) { \ 900 u_int32_t l; \ 901 if ((len -= CILEN_ADDRS) < 0) \ 902 goto bad; \ 903 GETCHAR(citype, p); \ 904 GETCHAR(cilen, p); \ 905 if (cilen != CILEN_ADDRS || \ 906 citype != opt) \ 907 goto bad; \ 908 GETLONG(l, p); \ 909 cilong = htonl(l); \ 910 if (val1 != cilong) \ 911 goto bad; \ 912 GETLONG(l, p); \ 913 cilong = htonl(l); \ 914 if (val2 != cilong) \ 915 goto bad; \ 916 } 917 918 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 919 if (neg) { \ 920 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 921 if ((len -= vjlen) < 0) \ 922 goto bad; \ 923 GETCHAR(citype, p); \ 924 GETCHAR(cilen, p); \ 925 if (cilen != vjlen || \ 926 citype != opt) \ 927 goto bad; \ 928 GETSHORT(cishort, p); \ 929 if (cishort != val) \ 930 goto bad; \ 931 if (!old) { \ 932 GETCHAR(cimaxslotindex, p); \ 933 if (cimaxslotindex != maxslotindex) \ 934 goto bad; \ 935 GETCHAR(cicflag, p); \ 936 if (cicflag != cflag) \ 937 goto bad; \ 938 } \ 939 } 940 941 #define ACKCIADDR(opt, neg, val) \ 942 if (neg) { \ 943 u_int32_t l; \ 944 if ((len -= CILEN_ADDR) < 0) \ 945 goto bad; \ 946 GETCHAR(citype, p); \ 947 GETCHAR(cilen, p); \ 948 if (cilen != CILEN_ADDR || \ 949 citype != opt) \ 950 goto bad; \ 951 GETLONG(l, p); \ 952 cilong = htonl(l); \ 953 if (val != cilong) \ 954 goto bad; \ 955 } 956 957 #define ACKCIDNS(opt, neg, addr) \ 958 if (neg) { \ 959 u_int32_t l; \ 960 if ((len -= CILEN_ADDR) < 0) \ 961 goto bad; \ 962 GETCHAR(citype, p); \ 963 GETCHAR(cilen, p); \ 964 if (cilen != CILEN_ADDR || citype != opt) \ 965 goto bad; \ 966 GETLONG(l, p); \ 967 cilong = htonl(l); \ 968 if (addr != cilong) \ 969 goto bad; \ 970 } 971 972 #define ACKCIWINS(opt, addr) \ 973 if (addr) { \ 974 u_int32_t l; \ 975 if ((len -= CILEN_ADDR) < 0) \ 976 goto bad; \ 977 GETCHAR(citype, p); \ 978 GETCHAR(cilen, p); \ 979 if (cilen != CILEN_ADDR || citype != opt) \ 980 goto bad; \ 981 GETLONG(l, p); \ 982 cilong = htonl(l); \ 983 if (addr != cilong) \ 984 goto bad; \ 985 } 986 987 ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, 988 go->hisaddr); 989 990 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 991 go->maxslotindex, go->cflag); 992 993 ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); 994 995 ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 996 997 ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 998 999 ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); 1000 1001 ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); 1002 1003 /* 1004 * If there are any remaining CIs, then this packet is bad. 1005 */ 1006 if (len != 0) 1007 goto bad; 1008 return (1); 1009 1010 bad: 1011 IPCPDEBUG(("ipcp_ackci: received bad Ack!")); 1012 return (0); 1013 } 1014 1015 /* 1016 * ipcp_nakci - Peer has sent a NAK for some of our CIs. 1017 * This should not modify any state if the Nak is bad 1018 * or if IPCP is in the OPENED state. 1019 * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. 1020 * 1021 * Returns: 1022 * 0 - Nak was bad. 1023 * 1 - Nak was good. 1024 */ 1025 static int 1026 ipcp_nakci(f, p, len, treat_as_reject) 1027 fsm *f; 1028 u_char *p; 1029 int len; 1030 int treat_as_reject; 1031 { 1032 ipcp_options *go = &ipcp_gotoptions[f->unit]; 1033 u_char cimaxslotindex, cicflag; 1034 u_char citype, cilen, *next; 1035 u_short cishort; 1036 u_int32_t ciaddr1, ciaddr2, l, cidnsaddr; 1037 ipcp_options no; /* options we've seen Naks for */ 1038 ipcp_options try; /* options to request next time */ 1039 1040 BZERO(&no, sizeof(no)); 1041 try = *go; 1042 1043 /* 1044 * Any Nak'd CIs must be in exactly the same order that we sent. 1045 * Check packet length and CI length at each step. 1046 * If we find any deviations, then this packet is bad. 1047 */ 1048 #define NAKCIADDRS(opt, neg, code) \ 1049 if ((neg) && \ 1050 (cilen = p[1]) == CILEN_ADDRS && \ 1051 len >= cilen && \ 1052 p[0] == opt) { \ 1053 len -= cilen; \ 1054 INCPTR(2, p); \ 1055 GETLONG(l, p); \ 1056 ciaddr1 = htonl(l); \ 1057 GETLONG(l, p); \ 1058 ciaddr2 = htonl(l); \ 1059 no.old_addrs = 1; \ 1060 code \ 1061 } 1062 1063 #define NAKCIVJ(opt, neg, code) \ 1064 if (go->neg && \ 1065 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ 1066 len >= cilen && \ 1067 p[0] == opt) { \ 1068 len -= cilen; \ 1069 INCPTR(2, p); \ 1070 GETSHORT(cishort, p); \ 1071 no.neg = 1; \ 1072 code \ 1073 } 1074 1075 #define NAKCIADDR(opt, neg, code) \ 1076 if (go->neg && \ 1077 (cilen = p[1]) == CILEN_ADDR && \ 1078 len >= cilen && \ 1079 p[0] == opt) { \ 1080 len -= cilen; \ 1081 INCPTR(2, p); \ 1082 GETLONG(l, p); \ 1083 ciaddr1 = htonl(l); \ 1084 no.neg = 1; \ 1085 code \ 1086 } 1087 1088 #define NAKCIDNS(opt, neg, code) \ 1089 if (go->neg && \ 1090 ((cilen = p[1]) == CILEN_ADDR) && \ 1091 len >= cilen && \ 1092 p[0] == opt) { \ 1093 len -= cilen; \ 1094 INCPTR(2, p); \ 1095 GETLONG(l, p); \ 1096 cidnsaddr = htonl(l); \ 1097 no.neg = 1; \ 1098 code \ 1099 } 1100 1101 /* 1102 * Accept the peer's idea of {our,his} address, if different 1103 * from our idea, only if the accept_{local,remote} flag is set. 1104 */ 1105 NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, 1106 if (treat_as_reject) { 1107 try.old_addrs = 0; 1108 } else { 1109 if (go->accept_local && ciaddr1) { 1110 /* take his idea of our address */ 1111 try.ouraddr = ciaddr1; 1112 } 1113 if (go->accept_remote && ciaddr2) { 1114 /* take his idea of his address */ 1115 try.hisaddr = ciaddr2; 1116 } 1117 } 1118 ); 1119 1120 /* 1121 * Accept the peer's value of maxslotindex provided that it 1122 * is less than what we asked for. Turn off slot-ID compression 1123 * if the peer wants. Send old-style compress-type option if 1124 * the peer wants. 1125 */ 1126 NAKCIVJ(CI_COMPRESSTYPE, neg_vj, 1127 if (treat_as_reject) { 1128 try.neg_vj = 0; 1129 } else if (cilen == CILEN_VJ) { 1130 GETCHAR(cimaxslotindex, p); 1131 GETCHAR(cicflag, p); 1132 if (cishort == IPCP_VJ_COMP) { 1133 try.old_vj = 0; 1134 if (cimaxslotindex < go->maxslotindex) 1135 try.maxslotindex = cimaxslotindex; 1136 if (!cicflag) 1137 try.cflag = 0; 1138 } else { 1139 try.neg_vj = 0; 1140 } 1141 } else { 1142 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { 1143 try.old_vj = 1; 1144 try.vj_protocol = cishort; 1145 } else { 1146 try.neg_vj = 0; 1147 } 1148 } 1149 ); 1150 1151 NAKCIADDR(CI_ADDR, neg_addr, 1152 if (treat_as_reject) { 1153 try.neg_addr = 0; 1154 try.old_addrs = 0; 1155 } else if (go->accept_local && ciaddr1) { 1156 /* take his idea of our address */ 1157 try.ouraddr = ciaddr1; 1158 } 1159 ); 1160 1161 NAKCIDNS(CI_MS_DNS1, req_dns1, 1162 if (treat_as_reject) { 1163 try.req_dns1 = 0; 1164 } else { 1165 try.dnsaddr[0] = cidnsaddr; 1166 } 1167 ); 1168 1169 NAKCIDNS(CI_MS_DNS2, req_dns2, 1170 if (treat_as_reject) { 1171 try.req_dns2 = 0; 1172 } else { 1173 try.dnsaddr[1] = cidnsaddr; 1174 } 1175 ); 1176 1177 /* 1178 * There may be remaining CIs, if the peer is requesting negotiation 1179 * on an option that we didn't include in our request packet. 1180 * If they want to negotiate about IP addresses, we comply. 1181 * If they want us to ask for compression, we refuse. 1182 * If they want us to ask for ms-dns, we do that, since some 1183 * peers get huffy if we don't. 1184 */ 1185 while (len >= CILEN_VOID) { 1186 GETCHAR(citype, p); 1187 GETCHAR(cilen, p); 1188 if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) 1189 goto bad; 1190 next = p + cilen - 2; 1191 1192 switch (citype) { 1193 case CI_COMPRESSTYPE: 1194 if (go->neg_vj || no.neg_vj || 1195 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) 1196 goto bad; 1197 no.neg_vj = 1; 1198 break; 1199 case CI_ADDRS: 1200 if ((!go->neg_addr && go->old_addrs) || no.old_addrs 1201 || cilen != CILEN_ADDRS) 1202 goto bad; 1203 try.neg_addr = 0; 1204 GETLONG(l, p); 1205 ciaddr1 = htonl(l); 1206 if (ciaddr1 && go->accept_local) 1207 try.ouraddr = ciaddr1; 1208 GETLONG(l, p); 1209 ciaddr2 = htonl(l); 1210 if (ciaddr2 && go->accept_remote) 1211 try.hisaddr = ciaddr2; 1212 no.old_addrs = 1; 1213 break; 1214 case CI_ADDR: 1215 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) 1216 goto bad; 1217 try.old_addrs = 0; 1218 GETLONG(l, p); 1219 ciaddr1 = htonl(l); 1220 if (ciaddr1 && go->accept_local) 1221 try.ouraddr = ciaddr1; 1222 if (try.ouraddr != 0) 1223 try.neg_addr = 1; 1224 no.neg_addr = 1; 1225 break; 1226 case CI_MS_DNS1: 1227 if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) 1228 goto bad; 1229 GETLONG(l, p); 1230 try.dnsaddr[0] = htonl(l); 1231 try.req_dns1 = 1; 1232 no.req_dns1 = 1; 1233 break; 1234 case CI_MS_DNS2: 1235 if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) 1236 goto bad; 1237 GETLONG(l, p); 1238 try.dnsaddr[1] = htonl(l); 1239 try.req_dns2 = 1; 1240 no.req_dns2 = 1; 1241 break; 1242 case CI_MS_WINS1: 1243 case CI_MS_WINS2: 1244 if (cilen != CILEN_ADDR) 1245 goto bad; 1246 GETLONG(l, p); 1247 ciaddr1 = htonl(l); 1248 if (ciaddr1) 1249 try.winsaddr[citype == CI_MS_WINS2] = ciaddr1; 1250 break; 1251 } 1252 p = next; 1253 } 1254 1255 /* 1256 * OK, the Nak is good. Now we can update state. 1257 * If there are any remaining options, we ignore them. 1258 */ 1259 if (f->state != OPENED) 1260 *go = try; 1261 1262 return 1; 1263 1264 bad: 1265 IPCPDEBUG(("ipcp_nakci: received bad Nak!")); 1266 return 0; 1267 } 1268 1269 1270 /* 1271 * ipcp_rejci - Reject some of our CIs. 1272 * Callback from fsm_rconfnakrej. 1273 */ 1274 static int 1275 ipcp_rejci(f, p, len) 1276 fsm *f; 1277 u_char *p; 1278 int len; 1279 { 1280 ipcp_options *go = &ipcp_gotoptions[f->unit]; 1281 u_char cimaxslotindex, ciflag, cilen; 1282 u_short cishort; 1283 u_int32_t cilong; 1284 ipcp_options try; /* options to request next time */ 1285 1286 try = *go; 1287 /* 1288 * Any Rejected CIs must be in exactly the same order that we sent. 1289 * Check packet length and CI length at each step. 1290 * If we find any deviations, then this packet is bad. 1291 */ 1292 #define REJCIADDRS(opt, neg, val1, val2) \ 1293 if ((neg) && \ 1294 (cilen = p[1]) == CILEN_ADDRS && \ 1295 len >= cilen && \ 1296 p[0] == opt) { \ 1297 u_int32_t l; \ 1298 len -= cilen; \ 1299 INCPTR(2, p); \ 1300 GETLONG(l, p); \ 1301 cilong = htonl(l); \ 1302 /* Check rejected value. */ \ 1303 if (cilong != val1) \ 1304 goto bad; \ 1305 GETLONG(l, p); \ 1306 cilong = htonl(l); \ 1307 /* Check rejected value. */ \ 1308 if (cilong != val2) \ 1309 goto bad; \ 1310 try.old_addrs = 0; \ 1311 } 1312 1313 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ 1314 if (go->neg && \ 1315 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ 1316 len >= p[1] && \ 1317 p[0] == opt) { \ 1318 len -= p[1]; \ 1319 INCPTR(2, p); \ 1320 GETSHORT(cishort, p); \ 1321 /* Check rejected value. */ \ 1322 if (cishort != val) \ 1323 goto bad; \ 1324 if (!old) { \ 1325 GETCHAR(cimaxslotindex, p); \ 1326 if (cimaxslotindex != maxslot) \ 1327 goto bad; \ 1328 GETCHAR(ciflag, p); \ 1329 if (ciflag != cflag) \ 1330 goto bad; \ 1331 } \ 1332 try.neg = 0; \ 1333 } 1334 1335 #define REJCIADDR(opt, neg, val) \ 1336 if (go->neg && \ 1337 (cilen = p[1]) == CILEN_ADDR && \ 1338 len >= cilen && \ 1339 p[0] == opt) { \ 1340 u_int32_t l; \ 1341 len -= cilen; \ 1342 INCPTR(2, p); \ 1343 GETLONG(l, p); \ 1344 cilong = htonl(l); \ 1345 /* Check rejected value. */ \ 1346 if (cilong != val) \ 1347 goto bad; \ 1348 try.neg = 0; \ 1349 } 1350 1351 #define REJCIDNS(opt, neg, dnsaddr) \ 1352 if (go->neg && \ 1353 ((cilen = p[1]) == CILEN_ADDR) && \ 1354 len >= cilen && \ 1355 p[0] == opt) { \ 1356 u_int32_t l; \ 1357 len -= cilen; \ 1358 INCPTR(2, p); \ 1359 GETLONG(l, p); \ 1360 cilong = htonl(l); \ 1361 /* Check rejected value. */ \ 1362 if (cilong != dnsaddr) \ 1363 goto bad; \ 1364 try.neg = 0; \ 1365 } 1366 1367 #define REJCIWINS(opt, addr) \ 1368 if (addr && \ 1369 ((cilen = p[1]) == CILEN_ADDR) && \ 1370 len >= cilen && \ 1371 p[0] == opt) { \ 1372 u_int32_t l; \ 1373 len -= cilen; \ 1374 INCPTR(2, p); \ 1375 GETLONG(l, p); \ 1376 cilong = htonl(l); \ 1377 /* Check rejected value. */ \ 1378 if (cilong != addr) \ 1379 goto bad; \ 1380 try.winsaddr[opt == CI_MS_WINS2] = 0; \ 1381 } 1382 1383 REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, 1384 go->ouraddr, go->hisaddr); 1385 1386 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, 1387 go->maxslotindex, go->cflag); 1388 1389 REJCIADDR(CI_ADDR, neg_addr, go->ouraddr); 1390 1391 REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); 1392 1393 REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); 1394 1395 REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); 1396 1397 REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); 1398 1399 /* 1400 * If there are any remaining CIs, then this packet is bad. 1401 */ 1402 if (len != 0) 1403 goto bad; 1404 /* 1405 * Now we can update state. 1406 */ 1407 if (f->state != OPENED) 1408 *go = try; 1409 return 1; 1410 1411 bad: 1412 IPCPDEBUG(("ipcp_rejci: received bad Reject!")); 1413 return 0; 1414 } 1415 1416 1417 /* 1418 * ipcp_reqci - Check the peer's requested CIs and send appropriate response. 1419 * Callback from fsm_rconfreq, Receive Configure Request 1420 * 1421 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified 1422 * appropriately. If reject_if_disagree is non-zero, doesn't return 1423 * CONFNAK; returns CONFREJ if it can't return CONFACK. 1424 */ 1425 static int 1426 ipcp_reqci(f, inp, len, reject_if_disagree) 1427 fsm *f; 1428 u_char *inp; /* Requested CIs */ 1429 int *len; /* Length of requested CIs */ 1430 int reject_if_disagree; 1431 { 1432 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 1433 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 1434 ipcp_options *ao = &ipcp_allowoptions[f->unit]; 1435 u_char *cip, *next; /* Pointer to current and next CIs */ 1436 u_short cilen, citype; /* Parsed len, type */ 1437 u_short cishort; /* Parsed short value */ 1438 u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ 1439 int rc = CONFACK; /* Final packet return code */ 1440 int orc; /* Individual option return code */ 1441 u_char *p; /* Pointer to next char to parse */ 1442 u_char *ucp = inp; /* Pointer to current output char */ 1443 int l = *len; /* Length left */ 1444 u_char maxslotindex, cflag; 1445 int d; 1446 1447 /* 1448 * Reset all his options. 1449 */ 1450 BZERO(ho, sizeof(*ho)); 1451 1452 /* 1453 * Process all his options. 1454 */ 1455 next = inp; 1456 while (l) { 1457 orc = CONFACK; /* Assume success */ 1458 cip = p = next; /* Remember begining of CI */ 1459 if (l < 2 || /* Not enough data for CI header or */ 1460 p[1] < 2 || /* CI length too small or */ 1461 p[1] > l) { /* CI length too big? */ 1462 IPCPDEBUG(("ipcp_reqci: bad CI length!")); 1463 orc = CONFREJ; /* Reject bad CI */ 1464 cilen = l; /* Reject till end of packet */ 1465 l = 0; /* Don't loop again */ 1466 goto endswitch; 1467 } 1468 GETCHAR(citype, p); /* Parse CI type */ 1469 GETCHAR(cilen, p); /* Parse CI length */ 1470 l -= cilen; /* Adjust remaining length */ 1471 next += cilen; /* Step to next CI */ 1472 1473 switch (citype) { /* Check CI type */ 1474 case CI_ADDRS: 1475 if (!ao->old_addrs || ho->neg_addr || 1476 cilen != CILEN_ADDRS) { /* Check CI length */ 1477 orc = CONFREJ; /* Reject CI */ 1478 break; 1479 } 1480 1481 /* 1482 * If he has no address, or if we both have his address but 1483 * disagree about it, then NAK it with our idea. 1484 * In particular, if we don't know his address, but he does, 1485 * then accept it. 1486 */ 1487 GETLONG(tl, p); /* Parse source address (his) */ 1488 ciaddr1 = htonl(tl); 1489 if (ciaddr1 != wo->hisaddr 1490 && (ciaddr1 == 0 || !wo->accept_remote)) { 1491 orc = CONFNAK; 1492 if (!reject_if_disagree) { 1493 DECPTR(sizeof(u_int32_t), p); 1494 tl = ntohl(wo->hisaddr); 1495 PUTLONG(tl, p); 1496 } 1497 } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 1498 /* 1499 * If neither we nor he knows his address, reject the option. 1500 */ 1501 orc = CONFREJ; 1502 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 1503 break; 1504 } 1505 1506 /* 1507 * If he doesn't know our address, or if we both have our address 1508 * but disagree about it, then NAK it with our idea. 1509 */ 1510 GETLONG(tl, p); /* Parse desination address (ours) */ 1511 ciaddr2 = htonl(tl); 1512 if (ciaddr2 != wo->ouraddr) { 1513 if (ciaddr2 == 0 || !wo->accept_local) { 1514 orc = CONFNAK; 1515 if (!reject_if_disagree) { 1516 DECPTR(sizeof(u_int32_t), p); 1517 tl = ntohl(wo->ouraddr); 1518 PUTLONG(tl, p); 1519 } 1520 } else { 1521 wo->ouraddr = ciaddr2; /* accept peer's idea */ 1522 } 1523 } 1524 1525 ho->old_addrs = 1; 1526 ho->hisaddr = ciaddr1; 1527 ho->ouraddr = ciaddr2; 1528 break; 1529 1530 case CI_ADDR: 1531 if (!ao->neg_addr || ho->old_addrs || 1532 cilen != CILEN_ADDR) { /* Check CI length */ 1533 orc = CONFREJ; /* Reject CI */ 1534 break; 1535 } 1536 1537 /* 1538 * If he has no address, or if we both have his address but 1539 * disagree about it, then NAK it with our idea. 1540 * In particular, if we don't know his address, but he does, 1541 * then accept it. 1542 */ 1543 GETLONG(tl, p); /* Parse source address (his) */ 1544 ciaddr1 = htonl(tl); 1545 if (ciaddr1 != wo->hisaddr 1546 && (ciaddr1 == 0 || !wo->accept_remote)) { 1547 orc = CONFNAK; 1548 if (!reject_if_disagree) { 1549 DECPTR(sizeof(u_int32_t), p); 1550 tl = ntohl(wo->hisaddr); 1551 PUTLONG(tl, p); 1552 } 1553 } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 1554 /* 1555 * Don't ACK an address of 0.0.0.0 - reject it instead. 1556 */ 1557 orc = CONFREJ; 1558 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 1559 break; 1560 } 1561 1562 ho->neg_addr = 1; 1563 ho->hisaddr = ciaddr1; 1564 break; 1565 1566 case CI_MS_DNS1: 1567 case CI_MS_DNS2: 1568 /* Microsoft primary or secondary DNS request */ 1569 d = citype == CI_MS_DNS2; 1570 1571 /* If we do not have a DNS address then we cannot send it */ 1572 if (ao->dnsaddr[d] == 0 || 1573 cilen != CILEN_ADDR) { /* Check CI length */ 1574 orc = CONFREJ; /* Reject CI */ 1575 break; 1576 } 1577 GETLONG(tl, p); 1578 if (htonl(tl) != ao->dnsaddr[d]) { 1579 DECPTR(sizeof(u_int32_t), p); 1580 tl = ntohl(ao->dnsaddr[d]); 1581 PUTLONG(tl, p); 1582 orc = CONFNAK; 1583 } 1584 break; 1585 1586 case CI_MS_WINS1: 1587 case CI_MS_WINS2: 1588 /* Microsoft primary or secondary WINS request */ 1589 d = citype == CI_MS_WINS2; 1590 1591 /* If we do not have a DNS address then we cannot send it */ 1592 if (ao->winsaddr[d] == 0 || 1593 cilen != CILEN_ADDR) { /* Check CI length */ 1594 orc = CONFREJ; /* Reject CI */ 1595 break; 1596 } 1597 GETLONG(tl, p); 1598 if (htonl(tl) != ao->winsaddr[d]) { 1599 DECPTR(sizeof(u_int32_t), p); 1600 tl = ntohl(ao->winsaddr[d]); 1601 PUTLONG(tl, p); 1602 orc = CONFNAK; 1603 } 1604 break; 1605 1606 case CI_COMPRESSTYPE: 1607 if (!ao->neg_vj || 1608 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { 1609 orc = CONFREJ; 1610 break; 1611 } 1612 GETSHORT(cishort, p); 1613 1614 if (!(cishort == IPCP_VJ_COMP || 1615 (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { 1616 orc = CONFREJ; 1617 break; 1618 } 1619 1620 ho->neg_vj = 1; 1621 ho->vj_protocol = cishort; 1622 if (cilen == CILEN_VJ) { 1623 GETCHAR(maxslotindex, p); 1624 if (maxslotindex > ao->maxslotindex) { 1625 orc = CONFNAK; 1626 if (!reject_if_disagree){ 1627 DECPTR(1, p); 1628 PUTCHAR(ao->maxslotindex, p); 1629 } 1630 } 1631 GETCHAR(cflag, p); 1632 if (cflag && !ao->cflag) { 1633 orc = CONFNAK; 1634 if (!reject_if_disagree){ 1635 DECPTR(1, p); 1636 PUTCHAR(wo->cflag, p); 1637 } 1638 } 1639 ho->maxslotindex = maxslotindex; 1640 ho->cflag = cflag; 1641 } else { 1642 ho->old_vj = 1; 1643 ho->maxslotindex = MAX_STATES - 1; 1644 ho->cflag = 1; 1645 } 1646 break; 1647 1648 default: 1649 orc = CONFREJ; 1650 break; 1651 } 1652 endswitch: 1653 if (orc == CONFACK && /* Good CI */ 1654 rc != CONFACK) /* but prior CI wasnt? */ 1655 continue; /* Don't send this one */ 1656 1657 if (orc == CONFNAK) { /* Nak this CI? */ 1658 if (reject_if_disagree) /* Getting fed up with sending NAKs? */ 1659 orc = CONFREJ; /* Get tough if so */ 1660 else { 1661 if (rc == CONFREJ) /* Rejecting prior CI? */ 1662 continue; /* Don't send this one */ 1663 if (rc == CONFACK) { /* Ack'd all prior CIs? */ 1664 rc = CONFNAK; /* Not anymore... */ 1665 ucp = inp; /* Backup */ 1666 } 1667 } 1668 } 1669 1670 if (orc == CONFREJ && /* Reject this CI */ 1671 rc != CONFREJ) { /* but no prior ones? */ 1672 rc = CONFREJ; 1673 ucp = inp; /* Backup */ 1674 } 1675 1676 /* Need to move CI? */ 1677 if (ucp != cip) 1678 BCOPY(cip, ucp, cilen); /* Move it */ 1679 1680 /* Update output pointer */ 1681 INCPTR(cilen, ucp); 1682 } 1683 1684 /* 1685 * If we aren't rejecting this packet, and we want to negotiate 1686 * their address, and they didn't send their address, then we 1687 * send a NAK with a CI_ADDR option appended. We assume the 1688 * input buffer is long enough that we can append the extra 1689 * option safely. 1690 */ 1691 if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && 1692 wo->req_addr && !reject_if_disagree && !noremoteip) { 1693 if (rc == CONFACK) { 1694 rc = CONFNAK; 1695 ucp = inp; /* reset pointer */ 1696 wo->req_addr = 0; /* don't ask again */ 1697 } 1698 PUTCHAR(CI_ADDR, ucp); 1699 PUTCHAR(CILEN_ADDR, ucp); 1700 tl = ntohl(wo->hisaddr); 1701 PUTLONG(tl, ucp); 1702 } 1703 1704 *len = ucp - inp; /* Compute output length */ 1705 IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); 1706 return (rc); /* Return final code */ 1707 } 1708 1709 1710 /* 1711 * ip_check_options - check that any IP-related options are OK, 1712 * and assign appropriate defaults. 1713 */ 1714 static void 1715 ip_check_options() 1716 { 1717 struct hostent *hp; 1718 u_int32_t local; 1719 ipcp_options *wo = &ipcp_wantoptions[0]; 1720 1721 /* 1722 * Default our local IP address based on our hostname. 1723 * If local IP address already given, don't bother. 1724 */ 1725 if (wo->ouraddr == 0 && !disable_defaultip) { 1726 /* 1727 * Look up our hostname (possibly with domain name appended) 1728 * and take the first IP address as our local IP address. 1729 * If there isn't an IP address for our hostname, too bad. 1730 */ 1731 wo->accept_local = 1; /* don't insist on this default value */ 1732 if ((hp = gethostbyname(hostname)) != NULL) { 1733 local = *(u_int32_t *)hp->h_addr; 1734 if (local != 0 && !bad_ip_adrs(local)) 1735 wo->ouraddr = local; 1736 } 1737 } 1738 ask_for_local = wo->ouraddr != 0 || !disable_defaultip; 1739 } 1740 1741 1742 /* 1743 * ip_demand_conf - configure the interface as though 1744 * IPCP were up, for use with dial-on-demand. 1745 */ 1746 static int 1747 ip_demand_conf(u) 1748 int u; 1749 { 1750 ipcp_options *wo = &ipcp_wantoptions[u]; 1751 1752 if (wo->hisaddr == 0 && !noremoteip) { 1753 /* make up an arbitrary address for the peer */ 1754 wo->hisaddr = htonl(0x0a707070 + ifunit); 1755 wo->accept_remote = 1; 1756 } 1757 if (wo->ouraddr == 0) { 1758 /* make up an arbitrary address for us */ 1759 wo->ouraddr = htonl(0x0a404040 + ifunit); 1760 wo->accept_local = 1; 1761 ask_for_local = 0; /* don't tell the peer this address */ 1762 } 1763 if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr))) 1764 return 0; 1765 ipcp_script(_PATH_IPPREUP, 1); 1766 if (!sifup(u)) 1767 return 0; 1768 if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE)) 1769 return 0; 1770 if (wo->default_route) 1771 if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr)) 1772 default_route_set[u] = 1; 1773 if (wo->proxy_arp) 1774 if (sifproxyarp(u, wo->hisaddr)) 1775 proxy_arp_set[u] = 1; 1776 1777 notice("local IP address %I", wo->ouraddr); 1778 if (wo->hisaddr) 1779 notice("remote IP address %I", wo->hisaddr); 1780 1781 return 1; 1782 } 1783 1784 1785 /* 1786 * ipcp_up - IPCP has come UP. 1787 * 1788 * Configure the IP network interface appropriately and bring it up. 1789 */ 1790 static void 1791 ipcp_up(f) 1792 fsm *f; 1793 { 1794 u_int32_t mask; 1795 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 1796 ipcp_options *go = &ipcp_gotoptions[f->unit]; 1797 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 1798 1799 IPCPDEBUG(("ipcp: up")); 1800 1801 /* 1802 * We must have a non-zero IP address for both ends of the link. 1803 */ 1804 if (!ho->neg_addr && !ho->old_addrs) 1805 ho->hisaddr = wo->hisaddr; 1806 1807 if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) 1808 && wo->ouraddr != 0) { 1809 error("Peer refused to agree to our IP address"); 1810 ipcp_close(f->unit, "Refused our IP address"); 1811 return; 1812 } 1813 if (go->ouraddr == 0) { 1814 error("Could not determine local IP address"); 1815 ipcp_close(f->unit, "Could not determine local IP address"); 1816 return; 1817 } 1818 if (ho->hisaddr == 0 && !noremoteip) { 1819 ho->hisaddr = htonl(0x0a404040 + ifunit); 1820 warn("Could not determine remote IP address: defaulting to %I", 1821 ho->hisaddr); 1822 } 1823 script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); 1824 if (ho->hisaddr != 0) 1825 script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); 1826 1827 if (!go->req_dns1) 1828 go->dnsaddr[0] = 0; 1829 if (!go->req_dns2) 1830 go->dnsaddr[1] = 0; 1831 if (go->dnsaddr[0]) 1832 script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); 1833 if (go->dnsaddr[1]) 1834 script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); 1835 if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { 1836 script_setenv("USEPEERDNS", "1", 0); 1837 create_resolv(go->dnsaddr[0], go->dnsaddr[1]); 1838 } 1839 1840 /* 1841 * Check that the peer is allowed to use the IP address it wants. 1842 */ 1843 if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { 1844 error("Peer is not authorized to use remote address %I", ho->hisaddr); 1845 ipcp_close(f->unit, "Unauthorized remote IP address"); 1846 return; 1847 } 1848 1849 /* set tcp compression */ 1850 sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); 1851 1852 /* 1853 * If we are doing dial-on-demand, the interface is already 1854 * configured, so we put out any saved-up packets, then set the 1855 * interface to pass IP packets. 1856 */ 1857 if (demand) { 1858 if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { 1859 ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr); 1860 if (go->ouraddr != wo->ouraddr) { 1861 warn("Local IP address changed to %I", go->ouraddr); 1862 script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); 1863 wo->ouraddr = go->ouraddr; 1864 } else 1865 script_unsetenv("OLDIPLOCAL"); 1866 if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { 1867 warn("Remote IP address changed to %I", ho->hisaddr); 1868 script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); 1869 wo->hisaddr = ho->hisaddr; 1870 } else 1871 script_unsetenv("OLDIPREMOTE"); 1872 1873 /* Set the interface to the new addresses */ 1874 mask = GetMask(go->ouraddr); 1875 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { 1876 if (debug) 1877 warn("Interface configuration failed"); 1878 ipcp_close(f->unit, "Interface configuration failed"); 1879 return; 1880 } 1881 1882 /* assign a default route through the interface if required */ 1883 if (ipcp_wantoptions[f->unit].default_route) 1884 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) 1885 default_route_set[f->unit] = 1; 1886 1887 /* Make a proxy ARP entry if requested. */ 1888 if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) 1889 if (sifproxyarp(f->unit, ho->hisaddr)) 1890 proxy_arp_set[f->unit] = 1; 1891 1892 } 1893 demand_rexmit(PPP_IP); 1894 sifnpmode(f->unit, PPP_IP, NPMODE_PASS); 1895 1896 } else { 1897 /* 1898 * Set IP addresses and (if specified) netmask. 1899 */ 1900 mask = GetMask(go->ouraddr); 1901 1902 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) 1903 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { 1904 if (debug) 1905 warn("Interface configuration failed"); 1906 ipcp_close(f->unit, "Interface configuration failed"); 1907 return; 1908 } 1909 #endif 1910 1911 /* run the pre-up script, if any, and wait for it to finish */ 1912 ipcp_script(_PATH_IPPREUP, 1); 1913 1914 /* bring the interface up for IP */ 1915 if (!sifup(f->unit)) { 1916 if (debug) 1917 warn("Interface failed to come up"); 1918 ipcp_close(f->unit, "Interface configuration failed"); 1919 return; 1920 } 1921 1922 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) 1923 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { 1924 if (debug) 1925 warn("Interface configuration failed"); 1926 ipcp_close(f->unit, "Interface configuration failed"); 1927 return; 1928 } 1929 #endif 1930 sifnpmode(f->unit, PPP_IP, NPMODE_PASS); 1931 1932 /* assign a default route through the interface if required */ 1933 if (ipcp_wantoptions[f->unit].default_route) 1934 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) 1935 default_route_set[f->unit] = 1; 1936 1937 /* Make a proxy ARP entry if requested. */ 1938 if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) 1939 if (sifproxyarp(f->unit, ho->hisaddr)) 1940 proxy_arp_set[f->unit] = 1; 1941 1942 ipcp_wantoptions[0].ouraddr = go->ouraddr; 1943 1944 notice("local IP address %I", go->ouraddr); 1945 if (ho->hisaddr != 0) 1946 notice("remote IP address %I", ho->hisaddr); 1947 if (go->dnsaddr[0]) 1948 notice("primary DNS address %I", go->dnsaddr[0]); 1949 if (go->dnsaddr[1]) 1950 notice("secondary DNS address %I", go->dnsaddr[1]); 1951 } 1952 1953 reset_link_stats(f->unit); 1954 1955 np_up(f->unit, PPP_IP); 1956 ipcp_is_up = 1; 1957 1958 notify(ip_up_notifier, 0); 1959 if (ip_up_hook) 1960 ip_up_hook(); 1961 1962 /* 1963 * Execute the ip-up script, like this: 1964 * /etc/ppp/ip-up interface tty speed local-IP remote-IP 1965 */ 1966 if (ipcp_script_state == s_down && ipcp_script_pid == 0) { 1967 ipcp_script_state = s_up; 1968 ipcp_script(_PATH_IPUP, 0); 1969 } 1970 } 1971 1972 1973 /* 1974 * ipcp_down - IPCP has gone DOWN. 1975 * 1976 * Take the IP network interface down, clear its addresses 1977 * and delete routes through it. 1978 */ 1979 static void 1980 ipcp_down(f) 1981 fsm *f; 1982 { 1983 IPCPDEBUG(("ipcp: down")); 1984 /* XXX a bit IPv4-centric here, we only need to get the stats 1985 * before the interface is marked down. */ 1986 /* XXX more correct: we must get the stats before running the notifiers, 1987 * at least for the radius plugin */ 1988 update_link_stats(f->unit); 1989 notify(ip_down_notifier, 0); 1990 if (ip_down_hook) 1991 ip_down_hook(); 1992 if (ipcp_is_up) { 1993 ipcp_is_up = 0; 1994 np_down(f->unit, PPP_IP); 1995 } 1996 sifvjcomp(f->unit, 0, 0, 0); 1997 1998 print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), 1999 * because print_link_stats() sets link_stats_valid 2000 * to 0 (zero) */ 2001 2002 /* 2003 * If we are doing dial-on-demand, set the interface 2004 * to queue up outgoing packets (for now). 2005 */ 2006 if (demand) { 2007 sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE); 2008 } else { 2009 sifnpmode(f->unit, PPP_IP, NPMODE_DROP); 2010 sifdown(f->unit); 2011 ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr, 2012 ipcp_hisoptions[f->unit].hisaddr); 2013 } 2014 2015 /* Execute the ip-down script */ 2016 if (ipcp_script_state == s_up && ipcp_script_pid == 0) { 2017 ipcp_script_state = s_down; 2018 ipcp_script(_PATH_IPDOWN, 0); 2019 } 2020 } 2021 2022 2023 /* 2024 * ipcp_clear_addrs() - clear the interface addresses, routes, 2025 * proxy arp entries, etc. 2026 */ 2027 static void 2028 ipcp_clear_addrs(unit, ouraddr, hisaddr) 2029 int unit; 2030 u_int32_t ouraddr; /* local address */ 2031 u_int32_t hisaddr; /* remote address */ 2032 { 2033 if (proxy_arp_set[unit]) { 2034 cifproxyarp(unit, hisaddr); 2035 proxy_arp_set[unit] = 0; 2036 } 2037 if (default_route_set[unit]) { 2038 cifdefaultroute(unit, ouraddr, hisaddr); 2039 default_route_set[unit] = 0; 2040 } 2041 cifaddr(unit, ouraddr, hisaddr); 2042 } 2043 2044 2045 /* 2046 * ipcp_finished - possibly shut down the lower layers. 2047 */ 2048 static void 2049 ipcp_finished(f) 2050 fsm *f; 2051 { 2052 if (ipcp_is_open) { 2053 ipcp_is_open = 0; 2054 np_finished(f->unit, PPP_IP); 2055 } 2056 } 2057 2058 2059 /* 2060 * ipcp_script_done - called when the ip-up or ip-down script 2061 * has finished. 2062 */ 2063 static void 2064 ipcp_script_done(arg) 2065 void *arg; 2066 { 2067 ipcp_script_pid = 0; 2068 switch (ipcp_script_state) { 2069 case s_up: 2070 if (ipcp_fsm[0].state != OPENED) { 2071 ipcp_script_state = s_down; 2072 ipcp_script(_PATH_IPDOWN, 0); 2073 } 2074 break; 2075 case s_down: 2076 if (ipcp_fsm[0].state == OPENED) { 2077 ipcp_script_state = s_up; 2078 ipcp_script(_PATH_IPUP, 0); 2079 } 2080 break; 2081 } 2082 } 2083 2084 2085 /* 2086 * ipcp_script - Execute a script with arguments 2087 * interface-name tty-name speed local-IP remote-IP. 2088 */ 2089 static void 2090 ipcp_script(script, wait) 2091 char *script; 2092 int wait; 2093 { 2094 char strspeed[32], strlocal[32], strremote[32]; 2095 char *argv[8]; 2096 2097 slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); 2098 slprintf(strlocal, sizeof(strlocal), "%I", ipcp_gotoptions[0].ouraddr); 2099 slprintf(strremote, sizeof(strremote), "%I", ipcp_hisoptions[0].hisaddr); 2100 2101 argv[0] = script; 2102 argv[1] = ifname; 2103 argv[2] = devnam; 2104 argv[3] = strspeed; 2105 argv[4] = strlocal; 2106 argv[5] = strremote; 2107 argv[6] = ipparam; 2108 argv[7] = NULL; 2109 if (wait) 2110 run_program(script, argv, 0, NULL, NULL, 1); 2111 else 2112 ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, 2113 NULL, 0); 2114 } 2115 2116 /* 2117 * create_resolv - create the replacement resolv.conf file 2118 */ 2119 static void 2120 create_resolv(peerdns1, peerdns2) 2121 u_int32_t peerdns1, peerdns2; 2122 { 2123 FILE *f; 2124 2125 f = fopen(_PATH_RESOLV, "w"); 2126 if (f == NULL) { 2127 error("Failed to create %s: %m", _PATH_RESOLV); 2128 return; 2129 } 2130 2131 if (peerdns1) 2132 fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1)); 2133 2134 if (peerdns2) 2135 fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2)); 2136 2137 if (ferror(f)) 2138 error("Write failed to %s: %m", _PATH_RESOLV); 2139 2140 fclose(f); 2141 } 2142 2143 /* 2144 * ipcp_printpkt - print the contents of an IPCP packet. 2145 */ 2146 static char *ipcp_codenames[] = { 2147 "ConfReq", "ConfAck", "ConfNak", "ConfRej", 2148 "TermReq", "TermAck", "CodeRej" 2149 }; 2150 2151 static int 2152 ipcp_printpkt(p, plen, printer, arg) 2153 u_char *p; 2154 int plen; 2155 void (*printer) __P((void *, char *, ...)); 2156 void *arg; 2157 { 2158 int code, id, len, olen; 2159 u_char *pstart, *optend; 2160 u_short cishort; 2161 u_int32_t cilong; 2162 2163 if (plen < HEADERLEN) 2164 return 0; 2165 pstart = p; 2166 GETCHAR(code, p); 2167 GETCHAR(id, p); 2168 GETSHORT(len, p); 2169 if (len < HEADERLEN || len > plen) 2170 return 0; 2171 2172 if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *)) 2173 printer(arg, " %s", ipcp_codenames[code-1]); 2174 else 2175 printer(arg, " code=0x%x", code); 2176 printer(arg, " id=0x%x", id); 2177 len -= HEADERLEN; 2178 switch (code) { 2179 case CONFREQ: 2180 case CONFACK: 2181 case CONFNAK: 2182 case CONFREJ: 2183 /* print option list */ 2184 while (len >= 2) { 2185 GETCHAR(code, p); 2186 GETCHAR(olen, p); 2187 p -= 2; 2188 if (olen < 2 || olen > len) { 2189 break; 2190 } 2191 printer(arg, " <"); 2192 len -= olen; 2193 optend = p + olen; 2194 switch (code) { 2195 case CI_ADDRS: 2196 if (olen == CILEN_ADDRS) { 2197 p += 2; 2198 GETLONG(cilong, p); 2199 printer(arg, "addrs %I", htonl(cilong)); 2200 GETLONG(cilong, p); 2201 printer(arg, " %I", htonl(cilong)); 2202 } 2203 break; 2204 case CI_COMPRESSTYPE: 2205 if (olen >= CILEN_COMPRESS) { 2206 p += 2; 2207 GETSHORT(cishort, p); 2208 printer(arg, "compress "); 2209 switch (cishort) { 2210 case IPCP_VJ_COMP: 2211 printer(arg, "VJ"); 2212 break; 2213 case IPCP_VJ_COMP_OLD: 2214 printer(arg, "old-VJ"); 2215 break; 2216 default: 2217 printer(arg, "0x%x", cishort); 2218 } 2219 } 2220 break; 2221 case CI_ADDR: 2222 if (olen == CILEN_ADDR) { 2223 p += 2; 2224 GETLONG(cilong, p); 2225 printer(arg, "addr %I", htonl(cilong)); 2226 } 2227 break; 2228 case CI_MS_DNS1: 2229 case CI_MS_DNS2: 2230 p += 2; 2231 GETLONG(cilong, p); 2232 printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2), 2233 htonl(cilong)); 2234 break; 2235 case CI_MS_WINS1: 2236 case CI_MS_WINS2: 2237 p += 2; 2238 GETLONG(cilong, p); 2239 printer(arg, "ms-wins %I", htonl(cilong)); 2240 break; 2241 } 2242 while (p < optend) { 2243 GETCHAR(code, p); 2244 printer(arg, " %.2x", code); 2245 } 2246 printer(arg, ">"); 2247 } 2248 break; 2249 2250 case TERMACK: 2251 case TERMREQ: 2252 if (len > 0 && *p >= ' ' && *p < 0x7f) { 2253 printer(arg, " "); 2254 print_string((char *)p, len, printer, arg); 2255 p += len; 2256 len = 0; 2257 } 2258 break; 2259 } 2260 2261 /* print the rest of the bytes in the packet */ 2262 for (; len > 0; --len) { 2263 GETCHAR(code, p); 2264 printer(arg, " %.2x", code); 2265 } 2266 2267 return p - pstart; 2268 } 2269 2270 /* 2271 * ip_active_pkt - see if this IP packet is worth bringing the link up for. 2272 * We don't bring the link up for IP fragments or for TCP FIN packets 2273 * with no data. 2274 */ 2275 #define IP_HDRLEN 20 /* bytes */ 2276 #define IP_OFFMASK 0x1fff 2277 #ifndef IPPROTO_TCP 2278 #define IPPROTO_TCP 6 2279 #endif 2280 #define TCP_HDRLEN 20 2281 #define TH_FIN 0x01 2282 2283 /* 2284 * We use these macros because the IP header may be at an odd address, 2285 * and some compilers might use word loads to get th_off or ip_hl. 2286 */ 2287 2288 #define net_short(x) (((x)[0] << 8) + (x)[1]) 2289 #define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) 2290 #define get_ipoff(x) net_short((unsigned char *)(x) + 6) 2291 #define get_ipproto(x) (((unsigned char *)(x))[9]) 2292 #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) 2293 #define get_tcpflags(x) (((unsigned char *)(x))[13]) 2294 2295 static int 2296 ip_active_pkt(pkt, len) 2297 u_char *pkt; 2298 int len; 2299 { 2300 u_char *tcp; 2301 int hlen; 2302 2303 len -= PPP_HDRLEN; 2304 pkt += PPP_HDRLEN; 2305 if (len < IP_HDRLEN) 2306 return 0; 2307 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) 2308 return 0; 2309 if (get_ipproto(pkt) != IPPROTO_TCP) 2310 return 1; 2311 hlen = get_iphl(pkt) * 4; 2312 if (len < hlen + TCP_HDRLEN) 2313 return 0; 2314 tcp = pkt + hlen; 2315 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) 2316 return 0; 2317 return 1; 2318 } 2319