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