1 /* 2 * ipcp.c - PPP IP Control Protocol. 3 * 4 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 5 * Use is subject to license terms. 6 * 7 * Copyright (c) 1989 Carnegie Mellon University. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms are permitted 11 * provided that the above copyright notice and this paragraph are 12 * duplicated in all such forms and that any documentation, 13 * advertising materials, and other materials related to such 14 * distribution and use acknowledge that the software was developed 15 * by Carnegie Mellon University. The name of the 16 * University may not be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21 */ 22 23 #pragma ident "%Z%%M% %I% %E% SMI" 24 #define RCSID "$Id: ipcp.c,v 1.54 2000/04/15 01:27:11 masputra Exp $" 25 26 /* 27 * TODO: 28 */ 29 30 #include <stdio.h> 31 #include <string.h> 32 #include <netdb.h> 33 #include <sys/param.h> 34 #include <sys/types.h> 35 #include <sys/socket.h> 36 #if defined(_linux_) || defined(__linux__) 37 #define __FAVOR_BSD 38 #endif 39 #include <netinet/in.h> 40 #include <netinet/tcp.h> 41 #include <arpa/inet.h> 42 43 #include "pppd.h" 44 #include "fsm.h" 45 #include "ipcp.h" 46 #include "pathnames.h" 47 48 #if !defined(lint) && !defined(_lint) 49 static const char rcsid[] = RCSID; 50 #endif 51 52 /* global vars */ 53 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ 54 ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ 55 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ 56 ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ 57 58 bool ipcp_from_hostname = 0; /* Local IP address is from hostname lookup */ 59 60 /* Hook for a plugin to know when IP protocol has come up */ 61 void (*ip_up_hook) __P((void)) = NULL; 62 63 /* Hook for a plugin to know when IP protocol has come down */ 64 void (*ip_down_hook) __P((void)) = NULL; 65 66 /* local vars */ 67 static bool default_route_set[NUM_PPP]; /* Have set up a default route */ 68 static bool proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ 69 static bool ipcp_is_up[NUM_PPP]; /* have called np_up() */ 70 static bool proxy_arp_quiet[NUM_PPP]; /* We should be quiet on error */ 71 static bool disable_defaultip = 0; /* Don't use hostname for IP addr */ 72 73 /* 74 * Callbacks for fsm code. (CI = Configuration Information) 75 */ 76 static void ipcp_resetci __P((fsm *)); /* Reset our CI */ 77 static int ipcp_cilen __P((fsm *)); /* Return length of our CI */ 78 static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */ 79 static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ 80 static int ipcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */ 81 static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ 82 static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ 83 static void ipcp_up __P((fsm *)); /* We're UP */ 84 static void ipcp_down __P((fsm *)); /* We're DOWN */ 85 static void ipcp_finished __P((fsm *)); /* Don't need lower layer */ 86 static int setmsservaddr __P((char *, u_int32_t *)); 87 88 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ 89 90 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ 91 ipcp_resetci, /* Reset our Configuration Information */ 92 ipcp_cilen, /* Length of our Configuration Information */ 93 ipcp_addci, /* Add our Configuration Information */ 94 ipcp_ackci, /* ACK our Configuration Information */ 95 ipcp_nakci, /* NAK our Configuration Information */ 96 ipcp_rejci, /* Reject our Configuration Information */ 97 ipcp_reqci, /* Request peer's Configuration Information */ 98 ipcp_up, /* Called when fsm reaches OPENED state */ 99 ipcp_down, /* Called when fsm leaves OPENED state */ 100 NULL, /* Called when we want the lower layer up */ 101 ipcp_finished, /* Called when we want the lower layer down */ 102 NULL, /* Retransmission is necessary */ 103 NULL, /* Called to handle protocol-specific codes */ 104 "IPCP", /* String name of protocol */ 105 NULL /* Peer rejected a code number */ 106 }; 107 108 /* 109 * Command-line options. 110 */ 111 static int setvjslots __P((char **)); 112 static int setdnsaddr __P((char **)); 113 static int setwinsaddr __P((char **)); 114 static int autoproxyarp __P((char **)); 115 116 static option_t ipcp_option_list[] = { 117 { "noip", o_bool, &ipcp_protent.enabled_flag, 118 "Disable IP and IPCP" }, 119 { "-ip", o_bool, &ipcp_protent.enabled_flag, 120 "Disable IP and IPCP" }, 121 { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, 122 "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj }, 123 { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, 124 "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj }, 125 { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, 126 "Disable VJ connection-ID compression", OPT_A2COPY, 127 &ipcp_allowoptions[0].cflag }, 128 { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, 129 "Disable VJ connection-ID compression", OPT_A2COPY, 130 &ipcp_allowoptions[0].cflag }, 131 { "vj-max-slots", o_special, (void *)setvjslots, 132 "Set maximum VJ header slots" }, 133 { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, 134 "Accept peer's address for us", 1 }, 135 { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, 136 "Accept peer's address for it", 1 }, 137 { "ipparam", o_string, &ipparam, 138 "Set ip script parameter" }, 139 { "noipdefault", o_bool, &disable_defaultip, 140 "Don't use name for default IP adrs", 1 }, 141 { "ms-dns", o_special, (void *)setdnsaddr, 142 "DNS address for the peer's use" }, 143 { "ms-wins", o_special, (void *)setwinsaddr, 144 "Nameserver for SMB over TCP/IP for peer" }, 145 { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, 146 "Set timeout for IPCP" }, 147 { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, 148 "Set max #xmits for term-reqs" }, 149 { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, 150 "Set max #xmits for conf-reqs" }, 151 { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, 152 "Set max #conf-naks for IPCP" }, 153 { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, 154 "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, 155 { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, 156 "disable defaultroute option", OPT_A2COPY, 157 &ipcp_wantoptions[0].default_route }, 158 { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, 159 "disable defaultroute option", OPT_A2COPY, 160 &ipcp_wantoptions[0].default_route }, 161 { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, 162 "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, 163 { "autoproxyarp", o_special_noarg, (void *)autoproxyarp, 164 "Add proxy ARP entry if needed", OPT_ENABLE, 165 &ipcp_allowoptions[0].proxy_arp }, 166 { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, 167 "disable proxyarp option", OPT_A2COPY, &ipcp_wantoptions[0].proxy_arp }, 168 { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, 169 "disable proxyarp option", OPT_A2COPY, &ipcp_wantoptions[0].proxy_arp }, 170 { "usepeerdns", o_bool, &ipcp_wantoptions[0].req_dns1, 171 "Ask peer for DNS address(es)", OPT_A2COPY|1, 172 &ipcp_wantoptions[0].req_dns2 }, 173 { NULL } 174 }; 175 176 /* 177 * Protocol entry points from main code. 178 */ 179 static void ipcp_init __P((int)); 180 static void ipcp_open __P((int)); 181 static void ipcp_close __P((int, char *)); 182 static void ipcp_lowerup __P((int)); 183 static void ipcp_lowerdown __P((int)); 184 static void ipcp_input __P((int, u_char *, int)); 185 static void ipcp_protrej __P((int)); 186 static int ipcp_printpkt __P((u_char *, int, 187 void (*) __P((void *, const char *, ...)), void *)); 188 static void ip_check_options __P((void)); 189 static int ip_demand_conf __P((int)); 190 static int ip_active_pkt __P((u_char *, int)); 191 static void ipcp_print_stat __P((int, FILE *)); 192 193 static void create_resolv __P((u_int32_t, u_int32_t)); 194 195 struct protent ipcp_protent = { 196 PPP_IPCP, 197 ipcp_init, 198 ipcp_input, 199 ipcp_protrej, 200 ipcp_lowerup, 201 ipcp_lowerdown, 202 ipcp_open, 203 ipcp_close, 204 ipcp_printpkt, 205 NULL, 206 1, 207 "IPCP", 208 "IP", 209 ipcp_option_list, 210 ip_check_options, 211 ip_demand_conf, 212 ip_active_pkt, 213 ipcp_print_stat 214 }; 215 216 static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t)); 217 static void ipcp_script __P((char *)); /* Run an up/down script */ 218 static void ipcp_script_done __P((void *, int)); 219 220 /* 221 * Lengths of configuration options. 222 */ 223 #define CILEN_VOID 2 224 #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ 225 #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ 226 #define CILEN_ADDR 6 /* new-style single address option */ 227 #define CILEN_ADDRS 10 /* old-style dual address option */ 228 229 230 /* 231 * This state variable is used to ensure that we don't 232 * run an ipcp-up/down script while one is already running. 233 */ 234 static enum script_state { 235 s_down, 236 s_up 237 } ipcp_script_state; 238 static pid_t ipcp_script_pid; 239 240 /* 241 * Make a string representation of a network IP address. 242 */ 243 char * 244 ip_ntoa(ipaddr) 245 u_int32_t ipaddr; 246 { 247 static char b[64]; 248 249 (void) slprintf(b, sizeof(b), "%I", ipaddr); 250 return b; 251 } 252 253 /* 254 * Option parsing. 255 */ 256 257 /* 258 * setvjslots - set maximum number of connection slots for VJ compression 259 */ 260 static int 261 setvjslots(argv) 262 char **argv; 263 { 264 int value; 265 266 if (!int_option(*argv, &value)) 267 return 0; 268 if (value < 2 || value > 16) { 269 option_error("vj-max-slots value must be between 2 and 16"); 270 return 0; 271 } 272 ipcp_wantoptions [0].maxslotindex = 273 ipcp_allowoptions[0].maxslotindex = value - 1; 274 return 1; 275 } 276 277 /* 278 * setmsservaddr - Set the primary and secondary server addresses in the 279 * array. setdnsaddr() and setwinsaddr() call this function with either 280 * dnsaddr[] or winsaddr[] as the serverarray argument. 281 */ 282 static int 283 setmsservaddr(servname, serverarray) 284 char *servname; 285 u_int32_t *serverarray; 286 { 287 u_int32_t addr; 288 struct hostent *hp = NULL; 289 290 addr = inet_addr(servname); 291 if (addr == (u_int32_t) -1) { 292 if ((hp = gethostbyname(servname)) == NULL) 293 return 0; 294 BCOPY(hp->h_addr, &addr, sizeof (u_int32_t)); 295 } 296 297 /* 298 * If there is no primary then this is the first instance of the 299 * option, we must set the primary. In that case, try to set the 300 * secondary to h_addr_list[1]. If the primary is already set, then 301 * this is the second instance of the option, and we must set 302 * the secondary. 303 */ 304 if (serverarray[0] == 0) { 305 serverarray[0] = addr; 306 if (hp != NULL && hp->h_addr_list[1] != NULL) 307 BCOPY(hp->h_addr_list[1], &serverarray[1], sizeof (u_int32_t)); 308 else 309 serverarray[1] = addr; 310 } else { 311 serverarray[1] = addr; 312 } 313 314 return (1); 315 } 316 317 /* 318 * setdnsaddr - set the dns address(es) 319 */ 320 static int 321 setdnsaddr(argv) 322 char **argv; 323 { 324 if (setmsservaddr(*argv, &(ipcp_allowoptions[0].dnsaddr[0])) == 0) { 325 option_error("invalid address parameter '%s' for ms-dns option", *argv); 326 return (0); 327 } 328 329 return (1); 330 } 331 332 /* 333 * setwinsaddr - set the wins address(es) 334 * This is primrarly used with the Samba package under UNIX or for pointing 335 * the caller to the existing WINS server on a Windows NT platform. 336 */ 337 static int 338 setwinsaddr(argv) 339 char **argv; 340 { 341 if (setmsservaddr(*argv, &(ipcp_allowoptions[0].winsaddr[0])) == 0) { 342 option_error("invalid address parameter '%s' for ms-wins option", 343 *argv); 344 return (0); 345 } 346 347 return (1); 348 } 349 350 /* 351 * autoproxyarp -- enable proxy ARP but don't emit error messages if 352 * it's not actually needed. 353 */ 354 /*ARGSUSED*/ 355 static int 356 autoproxyarp(argv) 357 char **argv; 358 { 359 ipcp_wantoptions[0].proxy_arp = 1; 360 proxy_arp_quiet[0] = 1; 361 362 return (1); 363 } 364 365 366 /* 367 * ipcp_init - Initialize IPCP. 368 */ 369 static void 370 ipcp_init(unit) 371 int unit; 372 { 373 fsm *f = &ipcp_fsm[unit]; 374 ipcp_options *wo = &ipcp_wantoptions[unit]; 375 ipcp_options *ao = &ipcp_allowoptions[unit]; 376 377 f->unit = unit; 378 f->protocol = PPP_IPCP; 379 f->callbacks = &ipcp_callbacks; 380 fsm_init(&ipcp_fsm[unit]); 381 382 BZERO(wo, sizeof(*wo)); 383 BZERO(ao, sizeof(*ao)); 384 385 wo->neg_addr = 1; 386 wo->neg_vj = 1; 387 wo->vj_protocol = IPCP_VJ_COMP; 388 wo->maxslotindex = MAX_STATES - 1; /* really max index */ 389 wo->cflag = 1; 390 391 ao->neg_addr = 1; 392 ao->neg_vj = 1; 393 ao->maxslotindex = MAX_STATES - 1; 394 ao->cflag = 1; 395 396 /* 397 * These aren't actually negotiated. Instead, they control 398 * whether the user may use the proxyarp and defaultroute options. 399 */ 400 ao->proxy_arp = 1; 401 ao->default_route = 1; 402 proxy_arp_quiet[unit] = 0; 403 } 404 405 406 /* 407 * ipcp_open - IPCP is allowed to come up. 408 */ 409 static void 410 ipcp_open(unit) 411 int unit; 412 { 413 fsm_open(&ipcp_fsm[unit]); 414 } 415 416 417 /* 418 * ipcp_close - Take IPCP down. 419 */ 420 static void 421 ipcp_close(unit, reason) 422 int unit; 423 char *reason; 424 { 425 fsm_close(&ipcp_fsm[unit], reason); 426 } 427 428 429 /* 430 * ipcp_lowerup - The lower layer is up. 431 */ 432 static void 433 ipcp_lowerup(unit) 434 int unit; 435 { 436 fsm_lowerup(&ipcp_fsm[unit]); 437 } 438 439 440 /* 441 * ipcp_lowerdown - The lower layer is down. 442 */ 443 static void 444 ipcp_lowerdown(unit) 445 int unit; 446 { 447 fsm_lowerdown(&ipcp_fsm[unit]); 448 } 449 450 451 /* 452 * ipcp_input - Input IPCP packet. 453 */ 454 static void 455 ipcp_input(unit, p, len) 456 int unit; 457 u_char *p; 458 int len; 459 { 460 fsm_input(&ipcp_fsm[unit], p, len); 461 } 462 463 464 /* 465 * ipcp_protrej - A Protocol-Reject was received for IPCP. 466 */ 467 static void 468 ipcp_protrej(unit) 469 int unit; 470 { 471 fsm_protreject(&ipcp_fsm[unit]); 472 } 473 474 475 /* 476 * ipcp_resetci - Reset our CI. 477 * Called by fsm_sconfreq, Send Configure Request. 478 */ 479 static void 480 ipcp_resetci(f) 481 fsm *f; 482 { 483 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 484 ipcp_options *go = &ipcp_gotoptions[f->unit]; 485 486 wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; 487 if (wo->ouraddr == 0 || disable_defaultip) 488 wo->accept_local = 1; 489 if (wo->hisaddr == 0) 490 wo->accept_remote = 1; 491 *go = *wo; 492 if (disable_defaultip) 493 go->ouraddr = 0; 494 } 495 496 497 /* 498 * ipcp_cilen - Return length of our CI. 499 * Called by fsm_sconfreq, Send Configure Request. 500 */ 501 static int 502 ipcp_cilen(f) 503 fsm *f; 504 { 505 ipcp_options *go = &ipcp_gotoptions[f->unit]; 506 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 507 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 508 509 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) 510 #define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) 511 #define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) 512 513 /* 514 * First see if we want to change our options to the old 515 * forms because we have received old forms from the peer. 516 */ 517 if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { 518 /* use the old style of address negotiation */ 519 go->neg_addr = 1; 520 go->old_addrs = 1; 521 } 522 if (wo->neg_vj && !go->neg_vj && !go->old_vj) { 523 /* try an older style of VJ negotiation */ 524 /* use the old style only if the peer did */ 525 if (ho->neg_vj && ho->old_vj) { 526 go->neg_vj = 1; 527 go->old_vj = 1; 528 go->vj_protocol = ho->vj_protocol; 529 } 530 } 531 532 return (LENCIADDR(go->neg_addr, go->old_addrs) + 533 LENCIVJ(go->neg_vj, go->old_vj) + 534 LENCIDNS(go->req_dns1) + 535 LENCIDNS(go->req_dns2)) ; 536 } 537 538 539 /* 540 * ipcp_addci - Add our desired CIs to a packet. 541 * Called by fsm_sconfreq, Send Configure Request. 542 */ 543 static void 544 ipcp_addci(f, ucp, lenp) 545 fsm *f; 546 u_char *ucp; 547 int *lenp; 548 { 549 ipcp_options *go = &ipcp_gotoptions[f->unit]; 550 int len = *lenp; 551 552 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 553 if (neg) { \ 554 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 555 if (len >= vjlen) { \ 556 PUTCHAR(opt, ucp); \ 557 PUTCHAR(vjlen, ucp); \ 558 PUTSHORT(val, ucp); \ 559 if (!old) { \ 560 PUTCHAR(maxslotindex, ucp); \ 561 PUTCHAR(cflag, ucp); \ 562 } \ 563 len -= vjlen; \ 564 } else \ 565 neg = 0; \ 566 } 567 568 #define ADDCIADDR(opt, neg, old, val1, val2) \ 569 if (neg) { \ 570 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ 571 if (len >= addrlen) { \ 572 PUTCHAR(opt, ucp); \ 573 PUTCHAR(addrlen, ucp); \ 574 PUTNLONG(val1, ucp); \ 575 if (old) { \ 576 PUTNLONG(val2, ucp); \ 577 } \ 578 len -= addrlen; \ 579 } else \ 580 neg = 0; \ 581 } 582 583 #define ADDCIDNS(opt, neg, addr) \ 584 if (neg) { \ 585 if (len >= CILEN_ADDR) { \ 586 PUTCHAR(opt, ucp); \ 587 PUTCHAR(CILEN_ADDR, ucp); \ 588 PUTNLONG(addr, ucp); \ 589 len -= CILEN_ADDR; \ 590 } else \ 591 neg = 0; \ 592 } 593 594 ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, 595 go->old_addrs, go->ouraddr, go->hisaddr); 596 597 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 598 go->maxslotindex, go->cflag); 599 600 ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 601 602 ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 603 604 *lenp -= len; 605 } 606 607 608 /* 609 * ipcp_ackci - Ack our CIs. 610 * Called by fsm_rconfack, Receive Configure ACK. 611 * 612 * Returns: 613 * 0 - Ack was bad. 614 * 1 - Ack was good. 615 */ 616 static int 617 ipcp_ackci(f, p, len) 618 fsm *f; 619 u_char *p; 620 int len; 621 { 622 ipcp_options *go = &ipcp_gotoptions[f->unit]; 623 u_short cilen, citype, cishort; 624 u_int32_t cilong; 625 u_char cimaxslotindex, cicflag; 626 627 /* 628 * CIs must be in exactly the same order that we sent... 629 * Check packet length and CI length at each step. 630 * If we find any deviations, then this packet is bad. 631 */ 632 633 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 634 if (neg) { \ 635 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 636 if ((len -= vjlen) < 0) \ 637 goto bad; \ 638 GETCHAR(citype, p); \ 639 GETCHAR(cilen, p); \ 640 if (cilen != vjlen || \ 641 citype != opt) \ 642 goto bad; \ 643 GETSHORT(cishort, p); \ 644 if (cishort != val) \ 645 goto bad; \ 646 if (!old) { \ 647 GETCHAR(cimaxslotindex, p); \ 648 if (cimaxslotindex != maxslotindex) \ 649 goto bad; \ 650 GETCHAR(cicflag, p); \ 651 if (cicflag != cflag) \ 652 goto bad; \ 653 } \ 654 } 655 656 #define ACKCIADDR(opt, neg, old, val1, val2) \ 657 if (neg) { \ 658 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ 659 if ((len -= addrlen) < 0) \ 660 goto bad; \ 661 GETCHAR(citype, p); \ 662 GETCHAR(cilen, p); \ 663 if (cilen != addrlen || \ 664 citype != opt) \ 665 goto bad; \ 666 GETNLONG(cilong, p); \ 667 if (val1 != cilong) \ 668 goto bad; \ 669 if (old) { \ 670 GETNLONG(cilong, p); \ 671 if (val2 != cilong) \ 672 goto bad; \ 673 } \ 674 } 675 676 #define ACKCIDNS(opt, neg, addr) \ 677 if (neg) { \ 678 if ((len -= CILEN_ADDR) < 0) \ 679 goto bad; \ 680 GETCHAR(citype, p); \ 681 GETCHAR(cilen, p); \ 682 if (cilen != CILEN_ADDR || citype != opt) \ 683 goto bad; \ 684 GETNLONG(cilong, p); \ 685 if (addr != cilong) \ 686 goto bad; \ 687 } 688 689 ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, 690 go->old_addrs, go->ouraddr, go->hisaddr); 691 692 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 693 go->maxslotindex, go->cflag); 694 695 ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 696 697 ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 698 699 /* 700 * If there are any remaining CIs, then this packet is bad. 701 */ 702 if (len != 0) 703 goto bad; 704 return (1); 705 706 bad: 707 IPCPDEBUG(("ipcp_ackci: received bad Ack!")); 708 return (0); 709 } 710 711 /* 712 * ipcp_nakci - Peer has sent a NAK for some of our CIs. 713 * This should not modify any state if the Nak is bad 714 * or if IPCP is in the OPENED state. 715 * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. 716 * 717 * Returns: 718 * 0 - Nak was bad. 719 * 1 - Nak was good. 720 */ 721 static int 722 ipcp_nakci(f, p, len) 723 fsm *f; 724 u_char *p; 725 int len; 726 { 727 ipcp_options *go = &ipcp_gotoptions[f->unit]; 728 u_char cimaxslotindex, cicflag; 729 u_char citype, cilen, *next; 730 u_short cishort; 731 u_int32_t ciaddr1, ciaddr2, cidnsaddr; 732 ipcp_options no; /* options we've seen Naks for */ 733 ipcp_options try; /* options to request next time */ 734 735 BZERO(&no, sizeof(no)); 736 try = *go; 737 738 /* 739 * Any Nak'd CIs must be in exactly the same order that we sent. 740 * Check packet length and CI length at each step. 741 * If we find any deviations, then this packet is bad. 742 */ 743 #define NAKCIADDR(opt, neg, old, code) \ 744 if (go->neg && \ 745 len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ 746 p[1] == cilen && \ 747 p[0] == opt) { \ 748 len -= cilen; \ 749 INCPTR(2, p); \ 750 GETNLONG(ciaddr1, p); \ 751 if (old) { \ 752 GETNLONG(ciaddr2, p); \ 753 no.old_addrs = 1; \ 754 } else \ 755 ciaddr2 = 0; \ 756 no.neg = 1; \ 757 code \ 758 } 759 760 #define NAKCIVJ(opt, neg, code) \ 761 if (go->neg && \ 762 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ 763 len >= cilen && \ 764 p[0] == opt) { \ 765 len -= cilen; \ 766 INCPTR(2, p); \ 767 GETSHORT(cishort, p); \ 768 no.neg = 1; \ 769 code \ 770 } 771 772 #define NAKCIDNS(opt, neg, code) \ 773 if (go->neg && \ 774 ((cilen = p[1]) == CILEN_ADDR) && \ 775 len >= cilen && \ 776 p[0] == opt) { \ 777 len -= cilen; \ 778 INCPTR(2, p); \ 779 GETNLONG(cidnsaddr, p); \ 780 no.neg = 1; \ 781 code \ 782 } 783 784 /* 785 * Accept the peer's idea of {our,his} address, if different 786 * from our idea, only if the accept_{local,remote} flag is set. 787 */ 788 NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, 789 if (go->accept_local && ciaddr1) { /* Do we know our address? */ 790 try.ouraddr = ciaddr1; 791 } 792 if (go->accept_remote && ciaddr2) { /* Does he know his? */ 793 try.hisaddr = ciaddr2; 794 } 795 ); 796 797 /* 798 * Accept the peer's value of maxslotindex provided that it 799 * is less than what we asked for. Turn off slot-ID compression 800 * if the peer wants. Send old-style compress-type option if 801 * the peer wants. 802 */ 803 NAKCIVJ(CI_COMPRESSTYPE, neg_vj, 804 if (cilen == CILEN_VJ) { 805 GETCHAR(cimaxslotindex, p); 806 GETCHAR(cicflag, p); 807 if (cishort == IPCP_VJ_COMP) { 808 try.old_vj = 0; 809 if (cimaxslotindex < go->maxslotindex) 810 try.maxslotindex = cimaxslotindex; 811 if (!cicflag) 812 try.cflag = 0; 813 } else { 814 try.neg_vj = 0; 815 } 816 } else { 817 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { 818 try.old_vj = 1; 819 try.vj_protocol = cishort; 820 } else { 821 try.neg_vj = 0; 822 } 823 } 824 ); 825 826 NAKCIDNS(CI_MS_DNS1, req_dns1, 827 try.dnsaddr[0] = cidnsaddr; 828 ); 829 830 NAKCIDNS(CI_MS_DNS2, req_dns2, 831 try.dnsaddr[1] = cidnsaddr; 832 ); 833 834 /* 835 * There may be remaining CIs, if the peer is requesting negotiation 836 * on an option that we didn't include in our request packet. 837 * If they want to negotiate about IP addresses, we comply. 838 * If they want us to ask for compression, we refuse. 839 */ 840 while (len > CILEN_VOID) { 841 GETCHAR(citype, p); 842 GETCHAR(cilen, p); 843 if( (len -= cilen) < 0 ) 844 goto bad; 845 next = p + cilen - 2; 846 847 switch (citype) { 848 case CI_COMPRESSTYPE: 849 if (go->neg_vj || no.neg_vj || 850 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) 851 goto bad; 852 no.neg_vj = 1; 853 break; 854 case CI_ADDRS: 855 if ((go->neg_addr && go->old_addrs) || no.old_addrs 856 || cilen != CILEN_ADDRS) 857 goto bad; 858 try.neg_addr = 1; 859 try.old_addrs = 1; 860 GETNLONG(ciaddr1, p); 861 if (ciaddr1 && go->accept_local) 862 try.ouraddr = ciaddr1; 863 GETNLONG(ciaddr2, p); 864 if (ciaddr2 && go->accept_remote) 865 try.hisaddr = ciaddr2; 866 no.old_addrs = 1; 867 break; 868 case CI_ADDR: 869 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) 870 goto bad; 871 try.old_addrs = 0; 872 GETNLONG(ciaddr1, p); 873 if (ciaddr1 && go->accept_local) 874 try.ouraddr = ciaddr1; 875 if (try.ouraddr != 0) 876 try.neg_addr = 1; 877 no.neg_addr = 1; 878 break; 879 } 880 p = next; 881 } 882 883 /* 884 * OK, the Nak is good. Now we can update state. 885 * If there are any remaining options, we ignore them. 886 */ 887 if (f->state != OPENED) 888 *go = try; 889 890 return 1; 891 892 bad: 893 IPCPDEBUG(("ipcp_nakci: received bad Nak!")); 894 return 0; 895 } 896 897 898 /* 899 * ipcp_rejci - Reject some of our CIs. 900 * Callback from fsm_rconfnakrej. 901 */ 902 static int 903 ipcp_rejci(f, p, len) 904 fsm *f; 905 u_char *p; 906 int len; 907 { 908 ipcp_options *go = &ipcp_gotoptions[f->unit]; 909 u_char cimaxslotindex, ciflag, cilen; 910 u_short cishort; 911 u_int32_t cilong; 912 ipcp_options try; /* options to request next time */ 913 914 try = *go; 915 /* 916 * Any Rejected CIs must be in exactly the same order that we sent. 917 * Check packet length and CI length at each step. 918 * If we find any deviations, then this packet is bad. 919 */ 920 #define REJCIADDR(opt, neg, old, val1, val2) \ 921 if (go->neg && \ 922 len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ 923 p[1] == cilen && \ 924 p[0] == opt) { \ 925 len -= cilen; \ 926 INCPTR(2, p); \ 927 GETNLONG(cilong, p); \ 928 /* Check rejected value. */ \ 929 if (cilong != val1) \ 930 goto bad; \ 931 if (old) { \ 932 GETNLONG(cilong, p); \ 933 /* Check rejected value. */ \ 934 if (cilong != val2) \ 935 goto bad; \ 936 } \ 937 try.neg = 0; \ 938 } 939 940 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ 941 if (go->neg && \ 942 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ 943 len >= p[1] && \ 944 p[0] == opt) { \ 945 len -= p[1]; \ 946 INCPTR(2, p); \ 947 GETSHORT(cishort, p); \ 948 /* Check rejected value. */ \ 949 if (cishort != val) \ 950 goto bad; \ 951 if (!old) { \ 952 GETCHAR(cimaxslotindex, p); \ 953 if (cimaxslotindex != maxslot) \ 954 goto bad; \ 955 GETCHAR(ciflag, p); \ 956 if (ciflag != cflag) \ 957 goto bad; \ 958 } \ 959 try.neg = 0; \ 960 } 961 962 #define REJCIDNS(opt, neg, dnsaddr) \ 963 if (go->neg && \ 964 ((cilen = p[1]) == CILEN_ADDR) && \ 965 len >= cilen && \ 966 p[0] == opt) { \ 967 len -= cilen; \ 968 INCPTR(2, p); \ 969 GETNLONG(cilong, p); \ 970 /* Check rejected value. */ \ 971 if (cilong != dnsaddr) \ 972 goto bad; \ 973 try.neg = 0; \ 974 } 975 976 977 REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, 978 go->old_addrs, go->ouraddr, go->hisaddr); 979 980 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, 981 go->maxslotindex, go->cflag); 982 983 REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); 984 985 REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); 986 987 /* 988 * If there are any remaining CIs, then this packet is bad. 989 */ 990 if (len != 0) 991 goto bad; 992 /* 993 * Now we can update state. 994 */ 995 if (f->state != OPENED) 996 *go = try; 997 return 1; 998 999 bad: 1000 IPCPDEBUG(("ipcp_rejci: received bad Reject!")); 1001 return 0; 1002 } 1003 1004 1005 /* 1006 * ipcp_reqci - Check the peer's requested CIs and send appropriate response. 1007 * Callback from fsm_rconfreq, Receive Configure Request 1008 * 1009 * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input 1010 * packet modified appropriately. If reject_if_disagree is non-zero, 1011 * doesn't return CODE_CONFNAK; returns CODE_CONFREJ if it can't 1012 * return CODE_CONFACK. 1013 */ 1014 static int 1015 ipcp_reqci(f, p, lenp, dont_nak) 1016 fsm *f; 1017 u_char *p; /* Requested CIs */ 1018 int *lenp; /* Length of requested CIs */ 1019 bool dont_nak; 1020 { 1021 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 1022 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 1023 ipcp_options *ao = &ipcp_allowoptions[f->unit]; 1024 ipcp_options *go = &ipcp_gotoptions[f->unit]; 1025 int ret, newret; 1026 u_char *p0, *nakp, *rejp, *prev; 1027 u_short cishort; 1028 int len, cilen, type; 1029 u_int32_t tl, ciaddr1, ciaddr2; /* Parsed address values */ 1030 u_char maxslotindex, cflag; 1031 int d; 1032 1033 ret = CODE_CONFACK; 1034 rejp = p0 = p; 1035 nakp = nak_buffer; 1036 1037 /* 1038 * Reset all his options. 1039 */ 1040 BZERO(ho, sizeof(*ho)); 1041 1042 /* 1043 * Process all his options. 1044 */ 1045 for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) { 1046 if ((len < 2) || p[1] > len) { 1047 /* 1048 * RFC 1661 page 40 -- if the option extends beyond the 1049 * packet, then discard the entire packet. 1050 */ 1051 return (0); 1052 } 1053 1054 newret = CODE_CONFACK; 1055 prev = p; 1056 GETCHAR(type, p); 1057