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