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