1 /** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and 2 dial-on-demand has been stripped. */ 3 /***************************************************************************** 4 * ipcp.c - Network PPP IP Control Protocol program file. 5 * 6 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 7 * portions Copyright (c) 1997 by Global Election Systems Inc. 8 * 9 * The authors hereby grant permission to use, copy, modify, distribute, 10 * and license this software and its documentation for any purpose, provided 11 * that existing copyright notices are retained in all copies and that this 12 * notice and the following disclaimer are included verbatim in any 13 * distributions. No written agreement, license, or royalty fee is required 14 * for any of the authorized uses. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 ****************************************************************************** 28 * REVISION HISTORY 29 * 30 * 03-01-01 Marc Boucher <marc@mbsi.ca> 31 * Ported to lwIP. 32 * 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 33 * Original. 34 *****************************************************************************/ 35 /* 36 * ipcp.c - PPP IP Control Protocol. 37 * 38 * Copyright (c) 1989 Carnegie Mellon University. 39 * All rights reserved. 40 * 41 * Redistribution and use in source and binary forms are permitted 42 * provided that the above copyright notice and this paragraph are 43 * duplicated in all such forms and that any documentation, 44 * advertising materials, and other materials related to such 45 * distribution and use acknowledge that the software was developed 46 * by Carnegie Mellon University. The name of the 47 * University may not be used to endorse or promote products derived 48 * from this software without specific prior written permission. 49 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 50 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 51 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 52 */ 53 54 #include "lwip/opt.h" 55 56 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 57 58 #include "ppp_impl.h" 59 #include "pppdebug.h" 60 61 #include "auth.h" 62 #include "fsm.h" 63 #include "vj.h" 64 #include "ipcp.h" 65 66 #include "lwip/inet.h" 67 68 #include <string.h> 69 70 /* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */ 71 72 /* global vars */ 73 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ 74 ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ 75 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ 76 ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ 77 78 /* local vars */ 79 static int default_route_set[NUM_PPP]; /* Have set up a default route */ 80 static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ 81 82 83 /* 84 * Callbacks for fsm code. (CI = Configuration Information) 85 */ 86 static void ipcp_resetci (fsm *); /* Reset our CI */ 87 static int ipcp_cilen (fsm *); /* Return length of our CI */ 88 static void ipcp_addci (fsm *, u_char *, int *); /* Add our CI */ 89 static int ipcp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */ 90 static int ipcp_nakci (fsm *, u_char *, int); /* Peer nak'd our CI */ 91 static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */ 92 static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */ 93 static void ipcp_up (fsm *); /* We're UP */ 94 static void ipcp_down (fsm *); /* We're DOWN */ 95 #if PPP_ADDITIONAL_CALLBACKS 96 static void ipcp_script (fsm *, char *); /* Run an up/down script */ 97 #endif 98 static void ipcp_finished (fsm *); /* Don't need lower layer */ 99 100 101 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ 102 103 104 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ 105 ipcp_resetci, /* Reset our Configuration Information */ 106 ipcp_cilen, /* Length of our Configuration Information */ 107 ipcp_addci, /* Add our Configuration Information */ 108 ipcp_ackci, /* ACK our Configuration Information */ 109 ipcp_nakci, /* NAK our Configuration Information */ 110 ipcp_rejci, /* Reject our Configuration Information */ 111 ipcp_reqci, /* Request peer's Configuration Information */ 112 ipcp_up, /* Called when fsm reaches LS_OPENED state */ 113 ipcp_down, /* Called when fsm leaves LS_OPENED state */ 114 NULL, /* Called when we want the lower layer up */ 115 ipcp_finished, /* Called when we want the lower layer down */ 116 NULL, /* Called when Protocol-Reject received */ 117 NULL, /* Retransmission is necessary */ 118 NULL, /* Called to handle protocol-specific codes */ 119 "IPCP" /* String name of protocol */ 120 }; 121 122 /* 123 * Protocol entry points from main code. 124 */ 125 static void ipcp_init (int); 126 static void ipcp_open (int); 127 static void ipcp_close (int, char *); 128 static void ipcp_lowerup (int); 129 static void ipcp_lowerdown (int); 130 static void ipcp_input (int, u_char *, int); 131 static void ipcp_protrej (int); 132 133 134 struct protent ipcp_protent = { 135 PPP_IPCP, 136 ipcp_init, 137 ipcp_input, 138 ipcp_protrej, 139 ipcp_lowerup, 140 ipcp_lowerdown, 141 ipcp_open, 142 ipcp_close, 143 #if PPP_ADDITIONAL_CALLBACKS 144 ipcp_printpkt, 145 NULL, 146 #endif /* PPP_ADDITIONAL_CALLBACKS */ 147 1, 148 "IPCP", 149 #if PPP_ADDITIONAL_CALLBACKS 150 ip_check_options, 151 NULL, 152 ip_active_pkt 153 #endif /* PPP_ADDITIONAL_CALLBACKS */ 154 }; 155 156 static void ipcp_clear_addrs (int); 157 158 /* 159 * Lengths of configuration options. 160 */ 161 #define CILEN_VOID 2 162 #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ 163 #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ 164 #define CILEN_ADDR 6 /* new-style single address option */ 165 #define CILEN_ADDRS 10 /* old-style dual address option */ 166 167 168 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ 169 (x) == CONFNAK ? "NAK" : "REJ") 170 171 172 /* 173 * ipcp_init - Initialize IPCP. 174 */ 175 static void 176 ipcp_init(int unit) 177 { 178 fsm *f = &ipcp_fsm[unit]; 179 ipcp_options *wo = &ipcp_wantoptions[unit]; 180 ipcp_options *ao = &ipcp_allowoptions[unit]; 181 182 f->unit = unit; 183 f->protocol = PPP_IPCP; 184 f->callbacks = &ipcp_callbacks; 185 fsm_init(&ipcp_fsm[unit]); 186 187 memset(wo, 0, sizeof(*wo)); 188 memset(ao, 0, sizeof(*ao)); 189 190 wo->neg_addr = 1; 191 wo->ouraddr = 0; 192 #if VJ_SUPPORT 193 wo->neg_vj = 1; 194 #else /* VJ_SUPPORT */ 195 wo->neg_vj = 0; 196 #endif /* VJ_SUPPORT */ 197 wo->vj_protocol = IPCP_VJ_COMP; 198 wo->maxslotindex = MAX_SLOTS - 1; 199 wo->cflag = 0; 200 wo->default_route = 1; 201 202 ao->neg_addr = 1; 203 #if VJ_SUPPORT 204 ao->neg_vj = 1; 205 #else /* VJ_SUPPORT */ 206 ao->neg_vj = 0; 207 #endif /* VJ_SUPPORT */ 208 ao->maxslotindex = MAX_SLOTS - 1; 209 ao->cflag = 1; 210 ao->default_route = 1; 211 } 212 213 214 /* 215 * ipcp_open - IPCP is allowed to come up. 216 */ 217 static void 218 ipcp_open(int unit) 219 { 220 fsm_open(&ipcp_fsm[unit]); 221 } 222 223 224 /* 225 * ipcp_close - Take IPCP down. 226 */ 227 static void 228 ipcp_close(int unit, char *reason) 229 { 230 fsm_close(&ipcp_fsm[unit], reason); 231 } 232 233 234 /* 235 * ipcp_lowerup - The lower layer is up. 236 */ 237 static void 238 ipcp_lowerup(int unit) 239 { 240 fsm_lowerup(&ipcp_fsm[unit]); 241 } 242 243 244 /* 245 * ipcp_lowerdown - The lower layer is down. 246 */ 247 static void 248 ipcp_lowerdown(int unit) 249 { 250 fsm_lowerdown(&ipcp_fsm[unit]); 251 } 252 253 254 /* 255 * ipcp_input - Input IPCP packet. 256 */ 257 static void 258 ipcp_input(int unit, u_char *p, int len) 259 { 260 fsm_input(&ipcp_fsm[unit], p, len); 261 } 262 263 264 /* 265 * ipcp_protrej - A Protocol-Reject was received for IPCP. 266 * 267 * Pretend the lower layer went down, so we shut up. 268 */ 269 static void 270 ipcp_protrej(int unit) 271 { 272 fsm_lowerdown(&ipcp_fsm[unit]); 273 } 274 275 276 /* 277 * ipcp_resetci - Reset our CI. 278 */ 279 static void 280 ipcp_resetci(fsm *f) 281 { 282 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 283 284 wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; 285 if (wo->ouraddr == 0) { 286 wo->accept_local = 1; 287 } 288 if (wo->hisaddr == 0) { 289 wo->accept_remote = 1; 290 } 291 /* Request DNS addresses from the peer */ 292 wo->req_dns1 = ppp_settings.usepeerdns; 293 wo->req_dns2 = ppp_settings.usepeerdns; 294 ipcp_gotoptions[f->unit] = *wo; 295 cis_received[f->unit] = 0; 296 } 297 298 299 /* 300 * ipcp_cilen - Return length of our CI. 301 */ 302 static int 303 ipcp_cilen(fsm *f) 304 { 305 ipcp_options *go = &ipcp_gotoptions[f->unit]; 306 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 307 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 308 309 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) 310 #define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) 311 #define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) 312 313 /* 314 * First see if we want to change our options to the old 315 * forms because we have received old forms from the peer. 316 */ 317 if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { 318 /* use the old style of address negotiation */ 319 go->neg_addr = 1; 320 go->old_addrs = 1; 321 } 322 if (wo->neg_vj && !go->neg_vj && !go->old_vj) { 323 /* try an older style of VJ negotiation */ 324 if (cis_received[f->unit] == 0) { 325 /* keep trying the new style until we see some CI from the peer */ 326 go->neg_vj = 1; 327 } else { 328 /* use the old style only if the peer did */ 329 if (ho->neg_vj && ho->old_vj) { 330 go->neg_vj = 1; 331 go->old_vj = 1; 332 go->vj_protocol = ho->vj_protocol; 333 } 334 } 335 } 336 337 return (LENCIADDR(go->neg_addr, go->old_addrs) + 338 LENCIVJ(go->neg_vj, go->old_vj) + 339 LENCIDNS(go->req_dns1) + 340 LENCIDNS(go->req_dns2)); 341 } 342 343 344 /* 345 * ipcp_addci - Add our desired CIs to a packet. 346 */ 347 static void 348 ipcp_addci(fsm *f, u_char *ucp, int *lenp) 349 { 350 ipcp_options *go = &ipcp_gotoptions[f->unit]; 351 int len = *lenp; 352 353 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 354 if (neg) { \ 355 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 356 if (len >= vjlen) { \ 357 PUTCHAR(opt, ucp); \ 358 PUTCHAR(vjlen, ucp); \ 359 PUTSHORT(val, ucp); \ 360 if (!old) { \ 361 PUTCHAR(maxslotindex, ucp); \ 362 PUTCHAR(cflag, ucp); \ 363 } \ 364 len -= vjlen; \ 365 } else { \ 366 neg = 0; \ 367 } \ 368 } 369 370 #define ADDCIADDR(opt, neg, old, val1, val2) \ 371 if (neg) { \ 372 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ 373 if (len >= addrlen) { \ 374 u32_t l; \ 375 PUTCHAR(opt, ucp); \ 376 PUTCHAR(addrlen, ucp); \ 377 l = ntohl(val1); \ 378 PUTLONG(l, ucp); \ 379 if (old) { \ 380 l = ntohl(val2); \ 381 PUTLONG(l, ucp); \ 382 } \ 383 len -= addrlen; \ 384 } else { \ 385 neg = 0; \ 386 } \ 387 } 388 389 #define ADDCIDNS(opt, neg, addr) \ 390 if (neg) { \ 391 if (len >= CILEN_ADDR) { \ 392 u32_t l; \ 393 PUTCHAR(opt, ucp); \ 394 PUTCHAR(CILEN_ADDR, ucp); \ 395 l = ntohl(addr); \ 396 PUTLONG(l, ucp); \ 397 len -= CILEN_ADDR; \ 398 } else { \ 399 neg = 0; \ 400 } \ 401 } 402 403 ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, 404 go->old_addrs, go->ouraddr, go->hisaddr); 405 406 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 407 go->maxslotindex, go->cflag); 408 409 ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 410 411 ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 412 413 *lenp -= len; 414 } 415 416 417 /* 418 * ipcp_ackci - Ack our CIs. 419 * 420 * Returns: 421 * 0 - Ack was bad. 422 * 1 - Ack was good. 423 */ 424 static int 425 ipcp_ackci(fsm *f, u_char *p, int len) 426 { 427 ipcp_options *go = &ipcp_gotoptions[f->unit]; 428 u_short cilen, citype, cishort; 429 u32_t cilong; 430 u_char cimaxslotindex, cicflag; 431 432 /* 433 * CIs must be in exactly the same order that we sent... 434 * Check packet length and CI length at each step. 435 * If we find any deviations, then this packet is bad. 436 */ 437 438 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 439 if (neg) { \ 440 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 441 if ((len -= vjlen) < 0) { \ 442 goto bad; \ 443 } \ 444 GETCHAR(citype, p); \ 445 GETCHAR(cilen, p); \ 446 if (cilen != vjlen || \ 447 citype != opt) { \ 448 goto bad; \ 449 } \ 450 GETSHORT(cishort, p); \ 451 if (cishort != val) { \ 452 goto bad; \ 453 } \ 454 if (!old) { \ 455 GETCHAR(cimaxslotindex, p); \ 456 if (cimaxslotindex != maxslotindex) { \ 457 goto bad; \ 458 } \ 459 GETCHAR(cicflag, p); \ 460 if (cicflag != cflag) { \ 461 goto bad; \ 462 } \ 463 } \ 464 } 465 466 #define ACKCIADDR(opt, neg, old, val1, val2) \ 467 if (neg) { \ 468 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ 469 u32_t l; \ 470 if ((len -= addrlen) < 0) { \ 471 goto bad; \ 472 } \ 473 GETCHAR(citype, p); \ 474 GETCHAR(cilen, p); \ 475 if (cilen != addrlen || \ 476 citype != opt) { \ 477 goto bad; \ 478 } \ 479 GETLONG(l, p); \ 480 cilong = htonl(l); \ 481 if (val1 != cilong) { \ 482 goto bad; \ 483 } \ 484 if (old) { \ 485 GETLONG(l, p); \ 486 cilong = htonl(l); \ 487 if (val2 != cilong) { \ 488 goto bad; \ 489 } \ 490 } \ 491 } 492 493 #define ACKCIDNS(opt, neg, addr) \ 494 if (neg) { \ 495 u32_t l; \ 496 if ((len -= CILEN_ADDR) < 0) { \ 497 goto bad; \ 498 } \ 499 GETCHAR(citype, p); \ 500 GETCHAR(cilen, p); \ 501 if (cilen != CILEN_ADDR || \ 502 citype != opt) { \ 503 goto bad; \ 504 } \ 505 GETLONG(l, p); \ 506 cilong = htonl(l); \ 507 if (addr != cilong) { \ 508 goto bad; \ 509 } \ 510 } 511 512 ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, 513 go->old_addrs, go->ouraddr, go->hisaddr); 514 515 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 516 go->maxslotindex, go->cflag); 517 518 ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 519 520 ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 521 522 /* 523 * If there are any remaining CIs, then this packet is bad. 524 */ 525 if (len != 0) { 526 goto bad; 527 } 528 return (1); 529 530 bad: 531 IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n")); 532 return (0); 533 } 534 535 /* 536 * ipcp_nakci - Peer has sent a NAK for some of our CIs. 537 * This should not modify any state if the Nak is bad 538 * or if IPCP is in the LS_OPENED state. 539 * 540 * Returns: 541 * 0 - Nak was bad. 542 * 1 - Nak was good. 543 */ 544 static int 545 ipcp_nakci(fsm *f, u_char *p, int len) 546 { 547 ipcp_options *go = &ipcp_gotoptions[f->unit]; 548 u_char cimaxslotindex, cicflag; 549 u_char citype, cilen, *next; 550 u_short cishort; 551 u32_t ciaddr1, ciaddr2, l, cidnsaddr; 552 ipcp_options no; /* options we've seen Naks for */ 553 ipcp_options try; /* options to request next time */ 554 555 BZERO(&no, sizeof(no)); 556 try = *go; 557 558 /* 559 * Any Nak'd CIs must be in exactly the same order that we sent. 560 * Check packet length and CI length at each step. 561 * If we find any deviations, then this packet is bad. 562 */ 563 #define NAKCIADDR(opt, neg, old, code) \ 564 if (go->neg && \ 565 len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ 566 p[1] == cilen && \ 567 p[0] == opt) { \ 568 len -= cilen; \ 569 INCPTR(2, p); \ 570 GETLONG(l, p); \ 571 ciaddr1 = htonl(l); \ 572 if (old) { \ 573 GETLONG(l, p); \ 574 ciaddr2 = htonl(l); \ 575 no.old_addrs = 1; \ 576 } else { \ 577 ciaddr2 = 0; \ 578 } \ 579 no.neg = 1; \ 580 code \ 581 } 582 583 #define NAKCIVJ(opt, neg, code) \ 584 if (go->neg && \ 585 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ 586 len >= cilen && \ 587 p[0] == opt) { \ 588 len -= cilen; \ 589 INCPTR(2, p); \ 590 GETSHORT(cishort, p); \ 591 no.neg = 1; \ 592 code \ 593 } 594 595 #define NAKCIDNS(opt, neg, code) \ 596 if (go->neg && \ 597 ((cilen = p[1]) == CILEN_ADDR) && \ 598 len >= cilen && \ 599 p[0] == opt) { \ 600 len -= cilen; \ 601 INCPTR(2, p); \ 602 GETLONG(l, p); \ 603 cidnsaddr = htonl(l); \ 604 no.neg = 1; \ 605 code \ 606 } 607 608 /* 609 * Accept the peer's idea of {our,his} address, if different 610 * from our idea, only if the accept_{local,remote} flag is set. 611 */ 612 NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, 613 if (go->accept_local && ciaddr1) { /* Do we know our address? */ 614 try.ouraddr = ciaddr1; 615 IPCPDEBUG(LOG_INFO, ("local IP address %s\n", 616 inet_ntoa(ciaddr1))); 617 } 618 if (go->accept_remote && ciaddr2) { /* Does he know his? */ 619 try.hisaddr = ciaddr2; 620 IPCPDEBUG(LOG_INFO, ("remote IP address %s\n", 621 inet_ntoa(ciaddr2))); 622 } 623 ); 624 625 /* 626 * Accept the peer's value of maxslotindex provided that it 627 * is less than what we asked for. Turn off slot-ID compression 628 * if the peer wants. Send old-style compress-type option if 629 * the peer wants. 630 */ 631 NAKCIVJ(CI_COMPRESSTYPE, neg_vj, 632 if (cilen == CILEN_VJ) { 633 GETCHAR(cimaxslotindex, p); 634 GETCHAR(cicflag, p); 635 if (cishort == IPCP_VJ_COMP) { 636 try.old_vj = 0; 637 if (cimaxslotindex < go->maxslotindex) { 638 try.maxslotindex = cimaxslotindex; 639 } 640 if (!cicflag) { 641 try.cflag = 0; 642 } 643 } else { 644 try.neg_vj = 0; 645 } 646 } else { 647 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { 648 try.old_vj = 1; 649 try.vj_protocol = cishort; 650 } else { 651 try.neg_vj = 0; 652 } 653 } 654 ); 655 656 NAKCIDNS(CI_MS_DNS1, req_dns1, 657 try.dnsaddr[0] = cidnsaddr; 658 IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr))); 659 ); 660 661 NAKCIDNS(CI_MS_DNS2, req_dns2, 662 try.dnsaddr[1] = cidnsaddr; 663 IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr))); 664 ); 665 666 /* 667 * There may be remaining CIs, if the peer is requesting negotiation 668 * on an option that we didn't include in our request packet. 669 * If they want to negotiate about IP addresses, we comply. 670 * If they want us to ask for compression, we refuse. 671 */ 672 while (len > CILEN_VOID) { 673 GETCHAR(citype, p); 674 GETCHAR(cilen, p); 675 if( (len -= cilen) < 0 ) { 676 goto bad; 677 } 678 next = p + cilen - 2; 679 680 switch (citype) { 681 case CI_COMPRESSTYPE: 682 if (go->neg_vj || no.neg_vj || 683 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { 684 goto bad; 685 } 686 no.neg_vj = 1; 687 break; 688 case CI_ADDRS: 689 if ((go->neg_addr && go->old_addrs) || no.old_addrs 690 || cilen != CILEN_ADDRS) { 691 goto bad; 692 } 693 try.neg_addr = 1; 694 try.old_addrs = 1; 695 GETLONG(l, p); 696 ciaddr1 = htonl(l); 697 if (ciaddr1 && go->accept_local) { 698 try.ouraddr = ciaddr1; 699 } 700 GETLONG(l, p); 701 ciaddr2 = htonl(l); 702 if (ciaddr2 && go->accept_remote) { 703 try.hisaddr = ciaddr2; 704 } 705 no.old_addrs = 1; 706 break; 707 case CI_ADDR: 708 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) { 709 goto bad; 710 } 711 try.old_addrs = 0; 712 GETLONG(l, p); 713 ciaddr1 = htonl(l); 714 if (ciaddr1 && go->accept_local) { 715 try.ouraddr = ciaddr1; 716 } 717 if (try.ouraddr != 0) { 718 try.neg_addr = 1; 719 } 720 no.neg_addr = 1; 721 break; 722 } 723 p = next; 724 } 725 726 /* If there is still anything left, this packet is bad. */ 727 if (len != 0) { 728 goto bad; 729 } 730 731 /* 732 * OK, the Nak is good. Now we can update state. 733 */ 734 if (f->state != LS_OPENED) { 735 *go = try; 736 } 737 738 return 1; 739 740 bad: 741 IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n")); 742 return 0; 743 } 744 745 746 /* 747 * ipcp_rejci - Reject some of our CIs. 748 */ 749 static int 750 ipcp_rejci(fsm *f, u_char *p, int len) 751 { 752 ipcp_options *go = &ipcp_gotoptions[f->unit]; 753 u_char cimaxslotindex, ciflag, cilen; 754 u_short cishort; 755 u32_t cilong; 756 ipcp_options try; /* options to request next time */ 757 758 try = *go; 759 /* 760 * Any Rejected CIs must be in exactly the same order that we sent. 761 * Check packet length and CI length at each step. 762 * If we find any deviations, then this packet is bad. 763 */ 764 #define REJCIADDR(opt, neg, old, val1, val2) \ 765 if (go->neg && \ 766 len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ 767 p[1] == cilen && \ 768 p[0] == opt) { \ 769 u32_t l; \ 770 len -= cilen; \ 771 INCPTR(2, p); \ 772 GETLONG(l, p); \ 773 cilong = htonl(l); \ 774 /* Check rejected value. */ \ 775 if (cilong != val1) { \ 776 goto bad; \ 777 } \ 778 if (old) { \ 779 GETLONG(l, p); \ 780 cilong = htonl(l); \ 781 /* Check rejected value. */ \ 782 if (cilong != val2) { \ 783 goto bad; \ 784 } \ 785 } \ 786 try.neg = 0; \ 787 } 788 789 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ 790 if (go->neg && \ 791 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ 792 len >= p[1] && \ 793 p[0] == opt) { \ 794 len -= p[1]; \ 795 INCPTR(2, p); \ 796 GETSHORT(cishort, p); \ 797 /* Check rejected value. */ \ 798 if (cishort != val) { \ 799 goto bad; \ 800 } \ 801 if (!old) { \ 802 GETCHAR(cimaxslotindex, p); \ 803 if (cimaxslotindex != maxslot) { \ 804 goto bad; \ 805 } \ 806 GETCHAR(ciflag, p); \ 807 if (ciflag != cflag) { \ 808 goto bad; \ 809 } \ 810 } \ 811 try.neg = 0; \ 812 } 813 814 #define REJCIDNS(opt, neg, dnsaddr) \ 815 if (go->neg && \ 816 ((cilen = p[1]) == CILEN_ADDR) && \ 817 len >= cilen && \ 818 p[0] == opt) { \ 819 u32_t l; \ 820 len -= cilen; \ 821 INCPTR(2, p); \ 822 GETLONG(l, p); \ 823 cilong = htonl(l); \ 824 /* Check rejected value. */ \ 825 if (cilong != dnsaddr) { \ 826 goto bad; \ 827 } \ 828 try.neg = 0; \ 829 } 830 831 REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, 832 go->old_addrs, go->ouraddr, go->hisaddr); 833 834 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, 835 go->maxslotindex, go->cflag); 836 837 REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); 838 839 REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); 840 841 /* 842 * If there are any remaining CIs, then this packet is bad. 843 */ 844 if (len != 0) { 845 goto bad; 846 } 847 /* 848 * Now we can update state. 849 */ 850 if (f->state != LS_OPENED) { 851 *go = try; 852 } 853 return 1; 854 855 bad: 856 IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n")); 857 return 0; 858 } 859 860 861 /* 862 * ipcp_reqci - Check the peer's requested CIs and send appropriate response. 863 * 864 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified 865 * appropriately. If reject_if_disagree is non-zero, doesn't return 866 * CONFNAK; returns CONFREJ if it can't return CONFACK. 867 */ 868 static int 869 ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree) 870 { 871 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 872 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 873 ipcp_options *ao = &ipcp_allowoptions[f->unit]; 874 #ifdef OLD_CI_ADDRS 875 ipcp_options *go = &ipcp_gotoptions[f->unit]; 876 #endif 877 u_char *cip, *next; /* Pointer to current and next CIs */ 878 u_short cilen, citype; /* Parsed len, type */ 879 u_short cishort; /* Parsed short value */ 880 u32_t tl, ciaddr1; /* Parsed address values */ 881 #ifdef OLD_CI_ADDRS 882 u32_t ciaddr2; /* Parsed address values */ 883 #endif 884 int rc = CONFACK; /* Final packet return code */ 885 int orc; /* Individual option return code */ 886 u_char *p; /* Pointer to next char to parse */ 887 u_char *ucp = inp; /* Pointer to current output char */ 888 int l = *len; /* Length left */ 889 u_char maxslotindex, cflag; 890 int d; 891 892 cis_received[f->unit] = 1; 893 894 /* 895 * Reset all his options. 896 */ 897 BZERO(ho, sizeof(*ho)); 898 899 /* 900 * Process all his options. 901 */ 902 next = inp; 903 while (l) { 904 orc = CONFACK; /* Assume success */ 905 cip = p = next; /* Remember begining of CI */ 906 if (l < 2 || /* Not enough data for CI header or */ 907 p[1] < 2 || /* CI length too small or */ 908 p[1] > l) { /* CI length too big? */ 909 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n")); 910 orc = CONFREJ; /* Reject bad CI */ 911 cilen = (u_short)l;/* Reject till end of packet */ 912 l = 0; /* Don't loop again */ 913 goto endswitch; 914 } 915 GETCHAR(citype, p); /* Parse CI type */ 916 GETCHAR(cilen, p); /* Parse CI length */ 917 l -= cilen; /* Adjust remaining length */ 918 next += cilen; /* Step to next CI */ 919 920 switch (citype) { /* Check CI type */ 921 #ifdef OLD_CI_ADDRS /* Need to save space... */ 922 case CI_ADDRS: 923 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n")); 924 if (!ao->neg_addr || 925 cilen != CILEN_ADDRS) { /* Check CI length */ 926 orc = CONFREJ; /* Reject CI */ 927 break; 928 } 929 930 /* 931 * If he has no address, or if we both have his address but 932 * disagree about it, then NAK it with our idea. 933 * In particular, if we don't know his address, but he does, 934 * then accept it. 935 */ 936 GETLONG(tl, p); /* Parse source address (his) */ 937 ciaddr1 = htonl(tl); 938 IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1))); 939 if (ciaddr1 != wo->hisaddr 940 && (ciaddr1 == 0 || !wo->accept_remote)) { 941 orc = CONFNAK; 942 if (!reject_if_disagree) { 943 DECPTR(sizeof(u32_t), p); 944 tl = ntohl(wo->hisaddr); 945 PUTLONG(tl, p); 946 } 947 } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 948 /* 949 * If neither we nor he knows his address, reject the option. 950 */ 951 orc = CONFREJ; 952 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 953 break; 954 } 955 956 /* 957 * If he doesn't know our address, or if we both have our address 958 * but disagree about it, then NAK it with our idea. 959 */ 960 GETLONG(tl, p); /* Parse desination address (ours) */ 961 ciaddr2 = htonl(tl); 962 IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2))); 963 if (ciaddr2 != wo->ouraddr) { 964 if (ciaddr2 == 0 || !wo->accept_local) { 965 orc = CONFNAK; 966 if (!reject_if_disagree) { 967 DECPTR(sizeof(u32_t), p); 968 tl = ntohl(wo->ouraddr); 969 PUTLONG(tl, p); 970 } 971 } else { 972 go->ouraddr = ciaddr2; /* accept peer's idea */ 973 } 974 } 975 976 ho->neg_addr = 1; 977 ho->old_addrs = 1; 978 ho->hisaddr = ciaddr1; 979 ho->ouraddr = ciaddr2; 980 break; 981 #endif 982 983 case CI_ADDR: 984 if (!ao->neg_addr) { 985 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n")); 986 orc = CONFREJ; /* Reject CI */ 987 break; 988 } else if (cilen != CILEN_ADDR) { /* Check CI length */ 989 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n")); 990 orc = CONFREJ; /* Reject CI */ 991 break; 992 } 993 994 /* 995 * If he has no address, or if we both have his address but 996 * disagree about it, then NAK it with our idea. 997 * In particular, if we don't know his address, but he does, 998 * then accept it. 999 */ 1000 GETLONG(tl, p); /* Parse source address (his) */ 1001 ciaddr1 = htonl(tl); 1002 if (ciaddr1 != wo->hisaddr 1003 && (ciaddr1 == 0 || !wo->accept_remote)) { 1004 orc = CONFNAK; 1005 if (!reject_if_disagree) { 1006 DECPTR(sizeof(u32_t), p); 1007 tl = ntohl(wo->hisaddr); 1008 PUTLONG(tl, p); 1009 } 1010 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1))); 1011 } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 1012 /* 1013 * Don't ACK an address of 0.0.0.0 - reject it instead. 1014 */ 1015 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1))); 1016 orc = CONFREJ; 1017 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 1018 break; 1019 } 1020 1021 ho->neg_addr = 1; 1022 ho->hisaddr = ciaddr1; 1023 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1))); 1024 break; 1025 1026 case CI_MS_DNS1: 1027 case CI_MS_DNS2: 1028 /* Microsoft primary or secondary DNS request */ 1029 d = citype == CI_MS_DNS2; 1030 1031 /* If we do not have a DNS address then we cannot send it */ 1032 if (ao->dnsaddr[d] == 0 || 1033 cilen != CILEN_ADDR) { /* Check CI length */ 1034 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1)); 1035 orc = CONFREJ; /* Reject CI */ 1036 break; 1037 } 1038 GETLONG(tl, p); 1039 if (htonl(tl) != ao->dnsaddr[d]) { 1040 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n", 1041 d+1, inet_ntoa(tl))); 1042 DECPTR(sizeof(u32_t), p); 1043 tl = ntohl(ao->dnsaddr[d]); 1044 PUTLONG(tl, p); 1045 orc = CONFNAK; 1046 } 1047 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1)); 1048 break; 1049 1050 case CI_MS_WINS1: 1051 case CI_MS_WINS2: 1052 /* Microsoft primary or secondary WINS request */ 1053 d = citype == CI_MS_WINS2; 1054 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1)); 1055 1056 /* If we do not have a DNS address then we cannot send it */ 1057 if (ao->winsaddr[d] == 0 || 1058 cilen != CILEN_ADDR) { /* Check CI length */ 1059 orc = CONFREJ; /* Reject CI */ 1060 break; 1061 } 1062 GETLONG(tl, p); 1063 if (htonl(tl) != ao->winsaddr[d]) { 1064 DECPTR(sizeof(u32_t), p); 1065 tl = ntohl(ao->winsaddr[d]); 1066 PUTLONG(tl, p); 1067 orc = CONFNAK; 1068 } 1069 break; 1070 1071 case CI_COMPRESSTYPE: 1072 if (!ao->neg_vj) { 1073 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n")); 1074 orc = CONFREJ; 1075 break; 1076 } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) { 1077 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen)); 1078 orc = CONFREJ; 1079 break; 1080 } 1081 GETSHORT(cishort, p); 1082 1083 if (!(cishort == IPCP_VJ_COMP || 1084 (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { 1085 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort)); 1086 orc = CONFREJ; 1087 break; 1088 } 1089 1090 ho->neg_vj = 1; 1091 ho->vj_protocol = cishort; 1092 if (cilen == CILEN_VJ) { 1093 GETCHAR(maxslotindex, p); 1094 if (maxslotindex > ao->maxslotindex) { 1095 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex)); 1096 orc = CONFNAK; 1097 if (!reject_if_disagree) { 1098 DECPTR(1, p); 1099 PUTCHAR(ao->maxslotindex, p); 1100 } 1101 } 1102 GETCHAR(cflag, p); 1103 if (cflag && !ao->cflag) { 1104 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag)); 1105 orc = CONFNAK; 1106 if (!reject_if_disagree) { 1107 DECPTR(1, p); 1108 PUTCHAR(wo->cflag, p); 1109 } 1110 } 1111 ho->maxslotindex = maxslotindex; 1112 ho->cflag = cflag; 1113 } else { 1114 ho->old_vj = 1; 1115 ho->maxslotindex = MAX_SLOTS - 1; 1116 ho->cflag = 1; 1117 } 1118 IPCPDEBUG(LOG_INFO, ( 1119 "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n", 1120 ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag)); 1121 break; 1122 1123 default: 1124 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype)); 1125 orc = CONFREJ; 1126 break; 1127 } 1128 1129 endswitch: 1130 if (orc == CONFACK && /* Good CI */ 1131 rc != CONFACK) { /* but prior CI wasnt? */ 1132 continue; /* Don't send this one */ 1133 } 1134 1135 if (orc == CONFNAK) { /* Nak this CI? */ 1136 if (reject_if_disagree) { /* Getting fed up with sending NAKs? */ 1137 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n")); 1138 orc = CONFREJ; /* Get tough if so */ 1139 } else { 1140 if (rc == CONFREJ) { /* Rejecting prior CI? */ 1141 continue; /* Don't send this one */ 1142 } 1143 if (rc == CONFACK) { /* Ack'd all prior CIs? */ 1144 rc = CONFNAK; /* Not anymore... */ 1145 ucp = inp; /* Backup */ 1146 } 1147 } 1148 } 1149 1150 if (orc == CONFREJ && /* Reject this CI */ 1151 rc != CONFREJ) { /* but no prior ones? */ 1152 rc = CONFREJ; 1153 ucp = inp; /* Backup */ 1154 } 1155 1156 /* Need to move CI? */ 1157 if (ucp != cip) { 1158 BCOPY(cip, ucp, cilen); /* Move it */ 1159 } 1160 1161 /* Update output pointer */ 1162 INCPTR(cilen, ucp); 1163 } 1164 1165 /* 1166 * If we aren't rejecting this packet, and we want to negotiate 1167 * their address, and they didn't send their address, then we 1168 * send a NAK with a CI_ADDR option appended. We assume the 1169 * input buffer is long enough that we can append the extra 1170 * option safely. 1171 */ 1172 if (rc != CONFREJ && !ho->neg_addr && 1173 wo->req_addr && !reject_if_disagree) { 1174 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n")); 1175 if (rc == CONFACK) { 1176 rc = CONFNAK; 1177 ucp = inp; /* reset pointer */ 1178 wo->req_addr = 0; /* don't ask again */ 1179 } 1180 PUTCHAR(CI_ADDR, ucp); 1181 PUTCHAR(CILEN_ADDR, ucp); 1182 tl = ntohl(wo->hisaddr); 1183 PUTLONG(tl, ucp); 1184 } 1185 1186 *len = (int)(ucp - inp); /* Compute output length */ 1187 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc))); 1188 return (rc); /* Return final code */ 1189 } 1190 1191 1192 #if 0 1193 /* 1194 * ip_check_options - check that any IP-related options are OK, 1195 * and assign appropriate defaults. 1196 */ 1197 static void 1198 ip_check_options(u_long localAddr) 1199 { 1200 ipcp_options *wo = &ipcp_wantoptions[0]; 1201 1202 /* 1203 * Load our default IP address but allow the remote host to give us 1204 * a new address. 1205 */ 1206 if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) { 1207 wo->accept_local = 1; /* don't insist on this default value */ 1208 wo->ouraddr = htonl(localAddr); 1209 } 1210 } 1211 #endif 1212 1213 1214 /* 1215 * ipcp_up - IPCP has come UP. 1216 * 1217 * Configure the IP network interface appropriately and bring it up. 1218 */ 1219 static void 1220 ipcp_up(fsm *f) 1221 { 1222 u32_t mask; 1223 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 1224 ipcp_options *go = &ipcp_gotoptions[f->unit]; 1225 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 1226 1227 np_up(f->unit, PPP_IP); 1228 IPCPDEBUG(LOG_INFO, ("ipcp: up\n")); 1229 1230 /* 1231 * We must have a non-zero IP address for both ends of the link. 1232 */ 1233 if (!ho->neg_addr) { 1234 ho->hisaddr = wo->hisaddr; 1235 } 1236 1237 if (ho->hisaddr == 0) { 1238 IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n")); 1239 ipcp_close(f->unit, "Could not determine remote IP address"); 1240 return; 1241 } 1242 if (go->ouraddr == 0) { 1243 IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n")); 1244 ipcp_close(f->unit, "Could not determine local IP address"); 1245 return; 1246 } 1247 1248 if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { 1249 /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/ 1250 } 1251 1252 /* 1253 * Check that the peer is allowed to use the IP address it wants. 1254 */ 1255 if (!auth_ip_addr(f->unit, ho->hisaddr)) { 1256 IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n", 1257 inet_ntoa(ho->hisaddr))); 1258 ipcp_close(f->unit, "Unauthorized remote IP address"); 1259 return; 1260 } 1261 1262 /* set tcp compression */ 1263 sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); 1264 1265 /* 1266 * Set IP addresses and (if specified) netmask. 1267 */ 1268 mask = GetMask(go->ouraddr); 1269 1270 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) { 1271 IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n")); 1272 ipcp_close(f->unit, "Interface configuration failed"); 1273 return; 1274 } 1275 1276 /* bring the interface up for IP */ 1277 if (!sifup(f->unit)) { 1278 IPCPDEBUG(LOG_WARNING, ("sifup failed\n")); 1279 ipcp_close(f->unit, "Interface configuration failed"); 1280 return; 1281 } 1282 1283 sifnpmode(f->unit, PPP_IP, NPMODE_PASS); 1284 1285 /* assign a default route through the interface if required */ 1286 if (ipcp_wantoptions[f->unit].default_route) { 1287 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) { 1288 default_route_set[f->unit] = 1; 1289 } 1290 } 1291 1292 IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr))); 1293 IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr))); 1294 if (go->dnsaddr[0]) { 1295 IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); 1296 } 1297 if (go->dnsaddr[1]) { 1298 IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); 1299 } 1300 } 1301 1302 1303 /* 1304 * ipcp_down - IPCP has gone DOWN. 1305 * 1306 * Take the IP network interface down, clear its addresses 1307 * and delete routes through it. 1308 */ 1309 static void 1310 ipcp_down(fsm *f) 1311 { 1312 IPCPDEBUG(LOG_INFO, ("ipcp: down\n")); 1313 np_down(f->unit, PPP_IP); 1314 sifvjcomp(f->unit, 0, 0, 0); 1315 1316 sifdown(f->unit); 1317 ipcp_clear_addrs(f->unit); 1318 } 1319 1320 1321 /* 1322 * ipcp_clear_addrs() - clear the interface addresses, routes, etc. 1323 */ 1324 static void 1325 ipcp_clear_addrs(int unit) 1326 { 1327 u32_t ouraddr, hisaddr; 1328 1329 ouraddr = ipcp_gotoptions[unit].ouraddr; 1330 hisaddr = ipcp_hisoptions[unit].hisaddr; 1331 if (default_route_set[unit]) { 1332 cifdefaultroute(unit, ouraddr, hisaddr); 1333 default_route_set[unit] = 0; 1334 } 1335 cifaddr(unit, ouraddr, hisaddr); 1336 } 1337 1338 1339 /* 1340 * ipcp_finished - possibly shut down the lower layers. 1341 */ 1342 static void 1343 ipcp_finished(fsm *f) 1344 { 1345 np_finished(f->unit, PPP_IP); 1346 } 1347 1348 #if PPP_ADDITIONAL_CALLBACKS 1349 static int 1350 ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) 1351 { 1352 LWIP_UNUSED_ARG(p); 1353 LWIP_UNUSED_ARG(plen); 1354 LWIP_UNUSED_ARG(printer); 1355 LWIP_UNUSED_ARG(arg); 1356 return 0; 1357 } 1358 1359 /* 1360 * ip_active_pkt - see if this IP packet is worth bringing the link up for. 1361 * We don't bring the link up for IP fragments or for TCP FIN packets 1362 * with no data. 1363 */ 1364 #define IP_HDRLEN 20 /* bytes */ 1365 #define IP_OFFMASK 0x1fff 1366 #define IPPROTO_TCP 6 1367 #define TCP_HDRLEN 20 1368 #define TH_FIN 0x01 1369 1370 /* 1371 * We use these macros because the IP header may be at an odd address, 1372 * and some compilers might use word loads to get th_off or ip_hl. 1373 */ 1374 1375 #define net_short(x) (((x)[0] << 8) + (x)[1]) 1376 #define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) 1377 #define get_ipoff(x) net_short((unsigned char *)(x) + 6) 1378 #define get_ipproto(x) (((unsigned char *)(x))[9]) 1379 #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) 1380 #define get_tcpflags(x) (((unsigned char *)(x))[13]) 1381 1382 static int 1383 ip_active_pkt(u_char *pkt, int len) 1384 { 1385 u_char *tcp; 1386 int hlen; 1387 1388 len -= PPP_HDRLEN; 1389 pkt += PPP_HDRLEN; 1390 if (len < IP_HDRLEN) { 1391 return 0; 1392 } 1393 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) { 1394 return 0; 1395 } 1396 if (get_ipproto(pkt) != IPPROTO_TCP) { 1397 return 1; 1398 } 1399 hlen = get_iphl(pkt) * 4; 1400 if (len < hlen + TCP_HDRLEN) { 1401 return 0; 1402 } 1403 tcp = pkt + hlen; 1404 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) { 1405 return 0; 1406 } 1407 return 1; 1408 } 1409 #endif /* PPP_ADDITIONAL_CALLBACKS */ 1410 1411 #endif /* PPP_SUPPORT */ 1412