Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip by
ipcp.c
00001 /** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and 00002 dial-on-demand has been stripped. */ 00003 /***************************************************************************** 00004 * ipcp.c - Network PPP IP Control Protocol program file. 00005 * 00006 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00007 * portions Copyright (c) 1997 by Global Election Systems Inc. 00008 * 00009 * The authors hereby grant permission to use, copy, modify, distribute, 00010 * and license this software and its documentation for any purpose, provided 00011 * that existing copyright notices are retained in all copies and that this 00012 * notice and the following disclaimer are included verbatim in any 00013 * distributions. No written agreement, license, or royalty fee is required 00014 * for any of the authorized uses. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00017 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00018 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00019 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00020 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00021 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00022 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00023 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00025 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 ****************************************************************************** 00028 * REVISION HISTORY 00029 * 00030 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00031 * Ported to lwIP. 00032 * 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00033 * Original. 00034 *****************************************************************************/ 00035 /* 00036 * ipcp.c - PPP IP Control Protocol. 00037 * 00038 * Copyright (c) 1989 Carnegie Mellon University. 00039 * All rights reserved. 00040 * 00041 * Redistribution and use in source and binary forms are permitted 00042 * provided that the above copyright notice and this paragraph are 00043 * duplicated in all such forms and that any documentation, 00044 * advertising materials, and other materials related to such 00045 * distribution and use acknowledge that the software was developed 00046 * by Carnegie Mellon University. The name of the 00047 * University may not be used to endorse or promote products derived 00048 * from this software without specific prior written permission. 00049 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00050 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00051 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00052 */ 00053 00054 #include "lwip/opt.h" 00055 00056 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00057 00058 #include "ppp.h" 00059 #include "pppdebug.h" 00060 00061 #include "auth.h" 00062 #include "fsm.h" 00063 #include "vj.h" 00064 #include "ipcp.h" 00065 00066 #include "lwip/inet.h" 00067 00068 #include <string.h> 00069 00070 /* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */ 00071 00072 /* global vars */ 00073 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ 00074 ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ 00075 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ 00076 ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ 00077 00078 /* local vars */ 00079 static int default_route_set[NUM_PPP]; /* Have set up a default route */ 00080 static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ 00081 00082 00083 /* 00084 * Callbacks for fsm code. (CI = Configuration Information) 00085 */ 00086 static void ipcp_resetci (fsm *); /* Reset our CI */ 00087 static int ipcp_cilen (fsm *); /* Return length of our CI */ 00088 static void ipcp_addci (fsm *, u_char *, int *); /* Add our CI */ 00089 static int ipcp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */ 00090 static int ipcp_nakci (fsm *, u_char *, int); /* Peer nak'd our CI */ 00091 static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */ 00092 static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */ 00093 static void ipcp_up (fsm *); /* We're UP */ 00094 static void ipcp_down (fsm *); /* We're DOWN */ 00095 #if PPP_ADDITIONAL_CALLBACKS 00096 static void ipcp_script (fsm *, char *); /* Run an up/down script */ 00097 #endif 00098 static void ipcp_finished (fsm *); /* Don't need lower layer */ 00099 00100 00101 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ 00102 00103 00104 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ 00105 ipcp_resetci, /* Reset our Configuration Information */ 00106 ipcp_cilen, /* Length of our Configuration Information */ 00107 ipcp_addci, /* Add our Configuration Information */ 00108 ipcp_ackci, /* ACK our Configuration Information */ 00109 ipcp_nakci, /* NAK our Configuration Information */ 00110 ipcp_rejci, /* Reject our Configuration Information */ 00111 ipcp_reqci, /* Request peer's Configuration Information */ 00112 ipcp_up, /* Called when fsm reaches LS_OPENED state */ 00113 ipcp_down, /* Called when fsm leaves LS_OPENED state */ 00114 NULL, /* Called when we want the lower layer up */ 00115 ipcp_finished, /* Called when we want the lower layer down */ 00116 NULL, /* Called when Protocol-Reject received */ 00117 NULL, /* Retransmission is necessary */ 00118 NULL, /* Called to handle protocol-specific codes */ 00119 "IPCP" /* String name of protocol */ 00120 }; 00121 00122 /* 00123 * Protocol entry points from main code. 00124 */ 00125 static void ipcp_init (int); 00126 static void ipcp_open (int); 00127 static void ipcp_close (int, char *); 00128 static void ipcp_lowerup (int); 00129 static void ipcp_lowerdown (int); 00130 static void ipcp_input (int, u_char *, int); 00131 static void ipcp_protrej (int); 00132 00133 00134 struct protent ipcp_protent = { 00135 PPP_IPCP, 00136 ipcp_init, 00137 ipcp_input, 00138 ipcp_protrej, 00139 ipcp_lowerup, 00140 ipcp_lowerdown, 00141 ipcp_open, 00142 ipcp_close, 00143 #if PPP_ADDITIONAL_CALLBACKS 00144 ipcp_printpkt, 00145 NULL, 00146 #endif /* PPP_ADDITIONAL_CALLBACKS */ 00147 1, 00148 "IPCP", 00149 #if PPP_ADDITIONAL_CALLBACKS 00150 ip_check_options, 00151 NULL, 00152 ip_active_pkt 00153 #endif /* PPP_ADDITIONAL_CALLBACKS */ 00154 }; 00155 00156 static void ipcp_clear_addrs (int); 00157 00158 /* 00159 * Lengths of configuration options. 00160 */ 00161 #define CILEN_VOID 2 00162 #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ 00163 #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ 00164 #define CILEN_ADDR 6 /* new-style single address option */ 00165 #define CILEN_ADDRS 10 /* old-style dual address option */ 00166 00167 00168 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ 00169 (x) == CONFNAK ? "NAK" : "REJ") 00170 00171 00172 /* 00173 * ipcp_init - Initialize IPCP. 00174 */ 00175 static void 00176 ipcp_init(int unit) 00177 { 00178 fsm *f = &ipcp_fsm[unit]; 00179 ipcp_options *wo = &ipcp_wantoptions[unit]; 00180 ipcp_options *ao = &ipcp_allowoptions[unit]; 00181 00182 f->unit = unit; 00183 f->protocol = PPP_IPCP; 00184 f->callbacks = &ipcp_callbacks; 00185 fsm_init(&ipcp_fsm[unit]); 00186 00187 memset(wo, 0, sizeof(*wo)); 00188 memset(ao, 0, sizeof(*ao)); 00189 00190 wo->neg_addr = 1; 00191 wo->ouraddr = 0; 00192 #if VJ_SUPPORT 00193 wo->neg_vj = 1; 00194 #else /* VJ_SUPPORT */ 00195 wo->neg_vj = 0; 00196 #endif /* VJ_SUPPORT */ 00197 wo->vj_protocol = IPCP_VJ_COMP; 00198 wo->maxslotindex = MAX_SLOTS - 1; 00199 wo->cflag = 0; 00200 wo->default_route = 1; 00201 00202 ao->neg_addr = 1; 00203 #if VJ_SUPPORT 00204 ao->neg_vj = 1; 00205 #else /* VJ_SUPPORT */ 00206 ao->neg_vj = 0; 00207 #endif /* VJ_SUPPORT */ 00208 ao->maxslotindex = MAX_SLOTS - 1; 00209 ao->cflag = 1; 00210 ao->default_route = 1; 00211 } 00212 00213 00214 /* 00215 * ipcp_open - IPCP is allowed to come up. 00216 */ 00217 static void 00218 ipcp_open(int unit) 00219 { 00220 fsm_open(&ipcp_fsm[unit]); 00221 } 00222 00223 00224 /* 00225 * ipcp_close - Take IPCP down. 00226 */ 00227 static void 00228 ipcp_close(int unit, char *reason) 00229 { 00230 fsm_close(&ipcp_fsm[unit], reason); 00231 } 00232 00233 00234 /* 00235 * ipcp_lowerup - The lower layer is up. 00236 */ 00237 static void 00238 ipcp_lowerup(int unit) 00239 { 00240 fsm_lowerup(&ipcp_fsm[unit]); 00241 } 00242 00243 00244 /* 00245 * ipcp_lowerdown - The lower layer is down. 00246 */ 00247 static void 00248 ipcp_lowerdown(int unit) 00249 { 00250 fsm_lowerdown(&ipcp_fsm[unit]); 00251 } 00252 00253 00254 /* 00255 * ipcp_input - Input IPCP packet. 00256 */ 00257 static void 00258 ipcp_input(int unit, u_char *p, int len) 00259 { 00260 fsm_input(&ipcp_fsm[unit], p, len); 00261 } 00262 00263 00264 /* 00265 * ipcp_protrej - A Protocol-Reject was received for IPCP. 00266 * 00267 * Pretend the lower layer went down, so we shut up. 00268 */ 00269 static void 00270 ipcp_protrej(int unit) 00271 { 00272 fsm_lowerdown(&ipcp_fsm[unit]); 00273 } 00274 00275 00276 /* 00277 * ipcp_resetci - Reset our CI. 00278 */ 00279 static void 00280 ipcp_resetci(fsm *f) 00281 { 00282 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 00283 00284 wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; 00285 if (wo->ouraddr == 0) { 00286 wo->accept_local = 1; 00287 } 00288 if (wo->hisaddr == 0) { 00289 wo->accept_remote = 1; 00290 } 00291 /* Request DNS addresses from the peer */ 00292 wo->req_dns1 = ppp_settings.usepeerdns; 00293 wo->req_dns2 = ppp_settings.usepeerdns; 00294 ipcp_gotoptions[f->unit] = *wo; 00295 cis_received[f->unit] = 0; 00296 } 00297 00298 00299 /* 00300 * ipcp_cilen - Return length of our CI. 00301 */ 00302 static int 00303 ipcp_cilen(fsm *f) 00304 { 00305 ipcp_options *go = &ipcp_gotoptions[f->unit]; 00306 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 00307 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 00308 00309 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) 00310 #define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) 00311 #define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) 00312 00313 /* 00314 * First see if we want to change our options to the old 00315 * forms because we have received old forms from the peer. 00316 */ 00317 if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { 00318 /* use the old style of address negotiation */ 00319 go->neg_addr = 1; 00320 go->old_addrs = 1; 00321 } 00322 if (wo->neg_vj && !go->neg_vj && !go->old_vj) { 00323 /* try an older style of VJ negotiation */ 00324 if (cis_received[f->unit] == 0) { 00325 /* keep trying the new style until we see some CI from the peer */ 00326 go->neg_vj = 1; 00327 } else { 00328 /* use the old style only if the peer did */ 00329 if (ho->neg_vj && ho->old_vj) { 00330 go->neg_vj = 1; 00331 go->old_vj = 1; 00332 go->vj_protocol = ho->vj_protocol; 00333 } 00334 } 00335 } 00336 00337 return (LENCIADDR(go->neg_addr, go->old_addrs) + 00338 LENCIVJ(go->neg_vj, go->old_vj) + 00339 LENCIDNS(go->req_dns1) + 00340 LENCIDNS(go->req_dns2)); 00341 } 00342 00343 00344 /* 00345 * ipcp_addci - Add our desired CIs to a packet. 00346 */ 00347 static void 00348 ipcp_addci(fsm *f, u_char *ucp, int *lenp) 00349 { 00350 ipcp_options *go = &ipcp_gotoptions[f->unit]; 00351 int len = *lenp; 00352 00353 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 00354 if (neg) { \ 00355 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 00356 if (len >= vjlen) { \ 00357 PUTCHAR(opt, ucp); \ 00358 PUTCHAR(vjlen, ucp); \ 00359 PUTSHORT(val, ucp); \ 00360 if (!old) { \ 00361 PUTCHAR(maxslotindex, ucp); \ 00362 PUTCHAR(cflag, ucp); \ 00363 } \ 00364 len -= vjlen; \ 00365 } else { \ 00366 neg = 0; \ 00367 } \ 00368 } 00369 00370 #define ADDCIADDR(opt, neg, old, val1, val2) \ 00371 if (neg) { \ 00372 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ 00373 if (len >= addrlen) { \ 00374 u32_t l; \ 00375 PUTCHAR(opt, ucp); \ 00376 PUTCHAR(addrlen, ucp); \ 00377 l = ntohl(val1); \ 00378 PUTLONG(l, ucp); \ 00379 if (old) { \ 00380 l = ntohl(val2); \ 00381 PUTLONG(l, ucp); \ 00382 } \ 00383 len -= addrlen; \ 00384 } else { \ 00385 neg = 0; \ 00386 } \ 00387 } 00388 00389 #define ADDCIDNS(opt, neg, addr) \ 00390 if (neg) { \ 00391 if (len >= CILEN_ADDR) { \ 00392 u32_t l; \ 00393 PUTCHAR(opt, ucp); \ 00394 PUTCHAR(CILEN_ADDR, ucp); \ 00395 l = ntohl(addr); \ 00396 PUTLONG(l, ucp); \ 00397 len -= CILEN_ADDR; \ 00398 } else { \ 00399 neg = 0; \ 00400 } \ 00401 } 00402 00403 ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, 00404 go->old_addrs, go->ouraddr, go->hisaddr); 00405 00406 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 00407 go->maxslotindex, go->cflag); 00408 00409 ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 00410 00411 ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 00412 00413 *lenp -= len; 00414 } 00415 00416 00417 /* 00418 * ipcp_ackci - Ack our CIs. 00419 * 00420 * Returns: 00421 * 0 - Ack was bad. 00422 * 1 - Ack was good. 00423 */ 00424 static int 00425 ipcp_ackci(fsm *f, u_char *p, int len) 00426 { 00427 ipcp_options *go = &ipcp_gotoptions[f->unit]; 00428 u_short cilen, citype, cishort; 00429 u32_t cilong; 00430 u_char cimaxslotindex, cicflag; 00431 00432 /* 00433 * CIs must be in exactly the same order that we sent... 00434 * Check packet length and CI length at each step. 00435 * If we find any deviations, then this packet is bad. 00436 */ 00437 00438 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 00439 if (neg) { \ 00440 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 00441 if ((len -= vjlen) < 0) { \ 00442 goto bad; \ 00443 } \ 00444 GETCHAR(citype, p); \ 00445 GETCHAR(cilen, p); \ 00446 if (cilen != vjlen || \ 00447 citype != opt) { \ 00448 goto bad; \ 00449 } \ 00450 GETSHORT(cishort, p); \ 00451 if (cishort != val) { \ 00452 goto bad; \ 00453 } \ 00454 if (!old) { \ 00455 GETCHAR(cimaxslotindex, p); \ 00456 if (cimaxslotindex != maxslotindex) { \ 00457 goto bad; \ 00458 } \ 00459 GETCHAR(cicflag, p); \ 00460 if (cicflag != cflag) { \ 00461 goto bad; \ 00462 } \ 00463 } \ 00464 } 00465 00466 #define ACKCIADDR(opt, neg, old, val1, val2) \ 00467 if (neg) { \ 00468 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ 00469 u32_t l; \ 00470 if ((len -= addrlen) < 0) { \ 00471 goto bad; \ 00472 } \ 00473 GETCHAR(citype, p); \ 00474 GETCHAR(cilen, p); \ 00475 if (cilen != addrlen || \ 00476 citype != opt) { \ 00477 goto bad; \ 00478 } \ 00479 GETLONG(l, p); \ 00480 cilong = htonl(l); \ 00481 if (val1 != cilong) { \ 00482 goto bad; \ 00483 } \ 00484 if (old) { \ 00485 GETLONG(l, p); \ 00486 cilong = htonl(l); \ 00487 if (val2 != cilong) { \ 00488 goto bad; \ 00489 } \ 00490 } \ 00491 } 00492 00493 #define ACKCIDNS(opt, neg, addr) \ 00494 if (neg) { \ 00495 u32_t l; \ 00496 if ((len -= CILEN_ADDR) < 0) { \ 00497 goto bad; \ 00498 } \ 00499 GETCHAR(citype, p); \ 00500 GETCHAR(cilen, p); \ 00501 if (cilen != CILEN_ADDR || \ 00502 citype != opt) { \ 00503 goto bad; \ 00504 } \ 00505 GETLONG(l, p); \ 00506 cilong = htonl(l); \ 00507 if (addr != cilong) { \ 00508 goto bad; \ 00509 } \ 00510 } 00511 00512 ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, 00513 go->old_addrs, go->ouraddr, go->hisaddr); 00514 00515 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 00516 go->maxslotindex, go->cflag); 00517 00518 ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 00519 00520 ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 00521 00522 /* 00523 * If there are any remaining CIs, then this packet is bad. 00524 */ 00525 if (len != 0) { 00526 goto bad; 00527 } 00528 return (1); 00529 00530 bad: 00531 IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n")); 00532 return (0); 00533 } 00534 00535 /* 00536 * ipcp_nakci - Peer has sent a NAK for some of our CIs. 00537 * This should not modify any state if the Nak is bad 00538 * or if IPCP is in the LS_OPENED state. 00539 * 00540 * Returns: 00541 * 0 - Nak was bad. 00542 * 1 - Nak was good. 00543 */ 00544 static int 00545 ipcp_nakci(fsm *f, u_char *p, int len) 00546 { 00547 ipcp_options *go = &ipcp_gotoptions[f->unit]; 00548 u_char cimaxslotindex, cicflag; 00549 u_char citype, cilen, *next; 00550 u_short cishort; 00551 u32_t ciaddr1, ciaddr2, l, cidnsaddr; 00552 ipcp_options no; /* options we've seen Naks for */ 00553 ipcp_options try; /* options to request next time */ 00554 00555 BZERO(&no, sizeof(no)); 00556 try = *go; 00557 00558 /* 00559 * Any Nak'd CIs must be in exactly the same order that we sent. 00560 * Check packet length and CI length at each step. 00561 * If we find any deviations, then this packet is bad. 00562 */ 00563 #define NAKCIADDR(opt, neg, old, code) \ 00564 if (go->neg && \ 00565 len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ 00566 p[1] == cilen && \ 00567 p[0] == opt) { \ 00568 len -= cilen; \ 00569 INCPTR(2, p); \ 00570 GETLONG(l, p); \ 00571 ciaddr1 = htonl(l); \ 00572 if (old) { \ 00573 GETLONG(l, p); \ 00574 ciaddr2 = htonl(l); \ 00575 no.old_addrs = 1; \ 00576 } else { \ 00577 ciaddr2 = 0; \ 00578 } \ 00579 no.neg = 1; \ 00580 code \ 00581 } 00582 00583 #define NAKCIVJ(opt, neg, code) \ 00584 if (go->neg && \ 00585 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ 00586 len >= cilen && \ 00587 p[0] == opt) { \ 00588 len -= cilen; \ 00589 INCPTR(2, p); \ 00590 GETSHORT(cishort, p); \ 00591 no.neg = 1; \ 00592 code \ 00593 } 00594 00595 #define NAKCIDNS(opt, neg, code) \ 00596 if (go->neg && \ 00597 ((cilen = p[1]) == CILEN_ADDR) && \ 00598 len >= cilen && \ 00599 p[0] == opt) { \ 00600 len -= cilen; \ 00601 INCPTR(2, p); \ 00602 GETLONG(l, p); \ 00603 cidnsaddr = htonl(l); \ 00604 no.neg = 1; \ 00605 code \ 00606 } 00607 00608 /* 00609 * Accept the peer's idea of {our,his} address, if different 00610 * from our idea, only if the accept_{local,remote} flag is set. 00611 */ 00612 NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, 00613 if (go->accept_local && ciaddr1) { /* Do we know our address? */ 00614 try.ouraddr = ciaddr1; 00615 IPCPDEBUG(LOG_INFO, ("local IP address %s\n", 00616 inet_ntoa(ciaddr1))); 00617 } 00618 if (go->accept_remote && ciaddr2) { /* Does he know his? */ 00619 try.hisaddr = ciaddr2; 00620 IPCPDEBUG(LOG_INFO, ("remote IP address %s\n", 00621 inet_ntoa(ciaddr2))); 00622 } 00623 ); 00624 00625 /* 00626 * Accept the peer's value of maxslotindex provided that it 00627 * is less than what we asked for. Turn off slot-ID compression 00628 * if the peer wants. Send old-style compress-type option if 00629 * the peer wants. 00630 */ 00631 NAKCIVJ(CI_COMPRESSTYPE, neg_vj, 00632 if (cilen == CILEN_VJ) { 00633 GETCHAR(cimaxslotindex, p); 00634 GETCHAR(cicflag, p); 00635 if (cishort == IPCP_VJ_COMP) { 00636 try.old_vj = 0; 00637 if (cimaxslotindex < go->maxslotindex) { 00638 try.maxslotindex = cimaxslotindex; 00639 } 00640 if (!cicflag) { 00641 try.cflag = 0; 00642 } 00643 } else { 00644 try.neg_vj = 0; 00645 } 00646 } else { 00647 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { 00648 try.old_vj = 1; 00649 try.vj_protocol = cishort; 00650 } else { 00651 try.neg_vj = 0; 00652 } 00653 } 00654 ); 00655 00656 NAKCIDNS(CI_MS_DNS1, req_dns1, 00657 try.dnsaddr[0] = cidnsaddr; 00658 IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr))); 00659 ); 00660 00661 NAKCIDNS(CI_MS_DNS2, req_dns2, 00662 try.dnsaddr[1] = cidnsaddr; 00663 IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr))); 00664 ); 00665 00666 /* 00667 * There may be remaining CIs, if the peer is requesting negotiation 00668 * on an option that we didn't include in our request packet. 00669 * If they want to negotiate about IP addresses, we comply. 00670 * If they want us to ask for compression, we refuse. 00671 */ 00672 while (len > CILEN_VOID) { 00673 GETCHAR(citype, p); 00674 GETCHAR(cilen, p); 00675 if( (len -= cilen) < 0 ) { 00676 goto bad; 00677 } 00678 next = p + cilen - 2; 00679 00680 switch (citype) { 00681 case CI_COMPRESSTYPE: 00682 if (go->neg_vj || no.neg_vj || 00683 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { 00684 goto bad; 00685 } 00686 no.neg_vj = 1; 00687 break; 00688 case CI_ADDRS: 00689 if ((go->neg_addr && go->old_addrs) || no.old_addrs 00690 || cilen != CILEN_ADDRS) { 00691 goto bad; 00692 } 00693 try.neg_addr = 1; 00694 try.old_addrs = 1; 00695 GETLONG(l, p); 00696 ciaddr1 = htonl(l); 00697 if (ciaddr1 && go->accept_local) { 00698 try.ouraddr = ciaddr1; 00699 } 00700 GETLONG(l, p); 00701 ciaddr2 = htonl(l); 00702 if (ciaddr2 && go->accept_remote) { 00703 try.hisaddr = ciaddr2; 00704 } 00705 no.old_addrs = 1; 00706 break; 00707 case CI_ADDR: 00708 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) { 00709 goto bad; 00710 } 00711 try.old_addrs = 0; 00712 GETLONG(l, p); 00713 ciaddr1 = htonl(l); 00714 if (ciaddr1 && go->accept_local) { 00715 try.ouraddr = ciaddr1; 00716 } 00717 if (try.ouraddr != 0) { 00718 try.neg_addr = 1; 00719 } 00720 no.neg_addr = 1; 00721 break; 00722 } 00723 p = next; 00724 } 00725 00726 /* If there is still anything left, this packet is bad. */ 00727 if (len != 0) { 00728 goto bad; 00729 } 00730 00731 /* 00732 * OK, the Nak is good. Now we can update state. 00733 */ 00734 if (f->state != LS_OPENED) { 00735 *go = try; 00736 } 00737 00738 return 1; 00739 00740 bad: 00741 IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n")); 00742 return 0; 00743 } 00744 00745 00746 /* 00747 * ipcp_rejci - Reject some of our CIs. 00748 */ 00749 static int 00750 ipcp_rejci(fsm *f, u_char *p, int len) 00751 { 00752 ipcp_options *go = &ipcp_gotoptions[f->unit]; 00753 u_char cimaxslotindex, ciflag, cilen; 00754 u_short cishort; 00755 u32_t cilong; 00756 ipcp_options try; /* options to request next time */ 00757 00758 try = *go; 00759 /* 00760 * Any Rejected CIs must be in exactly the same order that we sent. 00761 * Check packet length and CI length at each step. 00762 * If we find any deviations, then this packet is bad. 00763 */ 00764 #define REJCIADDR(opt, neg, old, val1, val2) \ 00765 if (go->neg && \ 00766 len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ 00767 p[1] == cilen && \ 00768 p[0] == opt) { \ 00769 u32_t l; \ 00770 len -= cilen; \ 00771 INCPTR(2, p); \ 00772 GETLONG(l, p); \ 00773 cilong = htonl(l); \ 00774 /* Check rejected value. */ \ 00775 if (cilong != val1) { \ 00776 goto bad; \ 00777 } \ 00778 if (old) { \ 00779 GETLONG(l, p); \ 00780 cilong = htonl(l); \ 00781 /* Check rejected value. */ \ 00782 if (cilong != val2) { \ 00783 goto bad; \ 00784 } \ 00785 } \ 00786 try.neg = 0; \ 00787 } 00788 00789 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ 00790 if (go->neg && \ 00791 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ 00792 len >= p[1] && \ 00793 p[0] == opt) { \ 00794 len -= p[1]; \ 00795 INCPTR(2, p); \ 00796 GETSHORT(cishort, p); \ 00797 /* Check rejected value. */ \ 00798 if (cishort != val) { \ 00799 goto bad; \ 00800 } \ 00801 if (!old) { \ 00802 GETCHAR(cimaxslotindex, p); \ 00803 if (cimaxslotindex != maxslot) { \ 00804 goto bad; \ 00805 } \ 00806 GETCHAR(ciflag, p); \ 00807 if (ciflag != cflag) { \ 00808 goto bad; \ 00809 } \ 00810 } \ 00811 try.neg = 0; \ 00812 } 00813 00814 #define REJCIDNS(opt, neg, dnsaddr) \ 00815 if (go->neg && \ 00816 ((cilen = p[1]) == CILEN_ADDR) && \ 00817 len >= cilen && \ 00818 p[0] == opt) { \ 00819 u32_t l; \ 00820 len -= cilen; \ 00821 INCPTR(2, p); \ 00822 GETLONG(l, p); \ 00823 cilong = htonl(l); \ 00824 /* Check rejected value. */ \ 00825 if (cilong != dnsaddr) { \ 00826 goto bad; \ 00827 } \ 00828 try.neg = 0; \ 00829 } 00830 00831 REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, 00832 go->old_addrs, go->ouraddr, go->hisaddr); 00833 00834 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, 00835 go->maxslotindex, go->cflag); 00836 00837 REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); 00838 00839 REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); 00840 00841 /* 00842 * If there are any remaining CIs, then this packet is bad. 00843 */ 00844 if (len != 0) { 00845 goto bad; 00846 } 00847 /* 00848 * Now we can update state. 00849 */ 00850 if (f->state != LS_OPENED) { 00851 *go = try; 00852 } 00853 return 1; 00854 00855 bad: 00856 IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n")); 00857 return 0; 00858 } 00859 00860 00861 /* 00862 * ipcp_reqci - Check the peer's requested CIs and send appropriate response. 00863 * 00864 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified 00865 * appropriately. If reject_if_disagree is non-zero, doesn't return 00866 * CONFNAK; returns CONFREJ if it can't return CONFACK. 00867 */ 00868 static int 00869 ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree) 00870 { 00871 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 00872 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 00873 ipcp_options *ao = &ipcp_allowoptions[f->unit]; 00874 #ifdef OLD_CI_ADDRS 00875 ipcp_options *go = &ipcp_gotoptions[f->unit]; 00876 #endif 00877 u_char *cip, *next; /* Pointer to current and next CIs */ 00878 u_short cilen, citype; /* Parsed len, type */ 00879 u_short cishort; /* Parsed short value */ 00880 u32_t tl, ciaddr1; /* Parsed address values */ 00881 #ifdef OLD_CI_ADDRS 00882 u32_t ciaddr2; /* Parsed address values */ 00883 #endif 00884 int rc = CONFACK; /* Final packet return code */ 00885 int orc; /* Individual option return code */ 00886 u_char *p; /* Pointer to next char to parse */ 00887 u_char *ucp = inp; /* Pointer to current output char */ 00888 int l = *len; /* Length left */ 00889 u_char maxslotindex, cflag; 00890 int d; 00891 00892 cis_received[f->unit] = 1; 00893 00894 /* 00895 * Reset all his options. 00896 */ 00897 BZERO(ho, sizeof(*ho)); 00898 00899 /* 00900 * Process all his options. 00901 */ 00902 next = inp; 00903 while (l) { 00904 orc = CONFACK; /* Assume success */ 00905 cip = p = next; /* Remember begining of CI */ 00906 if (l < 2 || /* Not enough data for CI header or */ 00907 p[1] < 2 || /* CI length too small or */ 00908 p[1] > l) { /* CI length too big? */ 00909 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n")); 00910 orc = CONFREJ; /* Reject bad CI */ 00911 cilen = (u_short)l;/* Reject till end of packet */ 00912 l = 0; /* Don't loop again */ 00913 goto endswitch; 00914 } 00915 GETCHAR(citype, p); /* Parse CI type */ 00916 GETCHAR(cilen, p); /* Parse CI length */ 00917 l -= cilen; /* Adjust remaining length */ 00918 next += cilen; /* Step to next CI */ 00919 00920 switch (citype) { /* Check CI type */ 00921 #ifdef OLD_CI_ADDRS /* Need to save space... */ 00922 case CI_ADDRS: 00923 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n")); 00924 if (!ao->neg_addr || 00925 cilen != CILEN_ADDRS) { /* Check CI length */ 00926 orc = CONFREJ; /* Reject CI */ 00927 break; 00928 } 00929 00930 /* 00931 * If he has no address, or if we both have his address but 00932 * disagree about it, then NAK it with our idea. 00933 * In particular, if we don't know his address, but he does, 00934 * then accept it. 00935 */ 00936 GETLONG(tl, p); /* Parse source address (his) */ 00937 ciaddr1 = htonl(tl); 00938 IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1))); 00939 if (ciaddr1 != wo->hisaddr 00940 && (ciaddr1 == 0 || !wo->accept_remote)) { 00941 orc = CONFNAK; 00942 if (!reject_if_disagree) { 00943 DECPTR(sizeof(u32_t), p); 00944 tl = ntohl(wo->hisaddr); 00945 PUTLONG(tl, p); 00946 } 00947 } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 00948 /* 00949 * If neither we nor he knows his address, reject the option. 00950 */ 00951 orc = CONFREJ; 00952 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 00953 break; 00954 } 00955 00956 /* 00957 * If he doesn't know our address, or if we both have our address 00958 * but disagree about it, then NAK it with our idea. 00959 */ 00960 GETLONG(tl, p); /* Parse desination address (ours) */ 00961 ciaddr2 = htonl(tl); 00962 IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2))); 00963 if (ciaddr2 != wo->ouraddr) { 00964 if (ciaddr2 == 0 || !wo->accept_local) { 00965 orc = CONFNAK; 00966 if (!reject_if_disagree) { 00967 DECPTR(sizeof(u32_t), p); 00968 tl = ntohl(wo->ouraddr); 00969 PUTLONG(tl, p); 00970 } 00971 } else { 00972 go->ouraddr = ciaddr2; /* accept peer's idea */ 00973 } 00974 } 00975 00976 ho->neg_addr = 1; 00977 ho->old_addrs = 1; 00978 ho->hisaddr = ciaddr1; 00979 ho->ouraddr = ciaddr2; 00980 break; 00981 #endif 00982 00983 case CI_ADDR: 00984 if (!ao->neg_addr) { 00985 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n")); 00986 orc = CONFREJ; /* Reject CI */ 00987 break; 00988 } else if (cilen != CILEN_ADDR) { /* Check CI length */ 00989 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n")); 00990 orc = CONFREJ; /* Reject CI */ 00991 break; 00992 } 00993 00994 /* 00995 * If he has no address, or if we both have his address but 00996 * disagree about it, then NAK it with our idea. 00997 * In particular, if we don't know his address, but he does, 00998 * then accept it. 00999 */ 01000 GETLONG(tl, p); /* Parse source address (his) */ 01001 ciaddr1 = htonl(tl); 01002 if (ciaddr1 != wo->hisaddr 01003 && (ciaddr1 == 0 || !wo->accept_remote)) { 01004 orc = CONFNAK; 01005 if (!reject_if_disagree) { 01006 DECPTR(sizeof(u32_t), p); 01007 tl = ntohl(wo->hisaddr); 01008 PUTLONG(tl, p); 01009 } 01010 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1))); 01011 } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 01012 /* 01013 * Don't ACK an address of 0.0.0.0 - reject it instead. 01014 */ 01015 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1))); 01016 orc = CONFREJ; 01017 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 01018 break; 01019 } 01020 01021 ho->neg_addr = 1; 01022 ho->hisaddr = ciaddr1; 01023 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1))); 01024 break; 01025 01026 case CI_MS_DNS1: 01027 case CI_MS_DNS2: 01028 /* Microsoft primary or secondary DNS request */ 01029 d = citype == CI_MS_DNS2; 01030 01031 /* If we do not have a DNS address then we cannot send it */ 01032 if (ao->dnsaddr[d] == 0 || 01033 cilen != CILEN_ADDR) { /* Check CI length */ 01034 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1)); 01035 orc = CONFREJ; /* Reject CI */ 01036 break; 01037 } 01038 GETLONG(tl, p); 01039 if (htonl(tl) != ao->dnsaddr[d]) { 01040 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n", 01041 d+1, inet_ntoa(tl))); 01042 DECPTR(sizeof(u32_t), p); 01043 tl = ntohl(ao->dnsaddr[d]); 01044 PUTLONG(tl, p); 01045 orc = CONFNAK; 01046 } 01047 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1)); 01048 break; 01049 01050 case CI_MS_WINS1: 01051 case CI_MS_WINS2: 01052 /* Microsoft primary or secondary WINS request */ 01053 d = citype == CI_MS_WINS2; 01054 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1)); 01055 01056 /* If we do not have a DNS address then we cannot send it */ 01057 if (ao->winsaddr[d] == 0 || 01058 cilen != CILEN_ADDR) { /* Check CI length */ 01059 orc = CONFREJ; /* Reject CI */ 01060 break; 01061 } 01062 GETLONG(tl, p); 01063 if (htonl(tl) != ao->winsaddr[d]) { 01064 DECPTR(sizeof(u32_t), p); 01065 tl = ntohl(ao->winsaddr[d]); 01066 PUTLONG(tl, p); 01067 orc = CONFNAK; 01068 } 01069 break; 01070 01071 case CI_COMPRESSTYPE: 01072 if (!ao->neg_vj) { 01073 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n")); 01074 orc = CONFREJ; 01075 break; 01076 } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) { 01077 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen)); 01078 orc = CONFREJ; 01079 break; 01080 } 01081 GETSHORT(cishort, p); 01082 01083 if (!(cishort == IPCP_VJ_COMP || 01084 (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { 01085 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort)); 01086 orc = CONFREJ; 01087 break; 01088 } 01089 01090 ho->neg_vj = 1; 01091 ho->vj_protocol = cishort; 01092 if (cilen == CILEN_VJ) { 01093 GETCHAR(maxslotindex, p); 01094 if (maxslotindex > ao->maxslotindex) { 01095 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex)); 01096 orc = CONFNAK; 01097 if (!reject_if_disagree) { 01098 DECPTR(1, p); 01099 PUTCHAR(ao->maxslotindex, p); 01100 } 01101 } 01102 GETCHAR(cflag, p); 01103 if (cflag && !ao->cflag) { 01104 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag)); 01105 orc = CONFNAK; 01106 if (!reject_if_disagree) { 01107 DECPTR(1, p); 01108 PUTCHAR(wo->cflag, p); 01109 } 01110 } 01111 ho->maxslotindex = maxslotindex; 01112 ho->cflag = cflag; 01113 } else { 01114 ho->old_vj = 1; 01115 ho->maxslotindex = MAX_SLOTS - 1; 01116 ho->cflag = 1; 01117 } 01118 IPCPDEBUG(LOG_INFO, ( 01119 "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n", 01120 ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag)); 01121 break; 01122 01123 default: 01124 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype)); 01125 orc = CONFREJ; 01126 break; 01127 } 01128 01129 endswitch: 01130 if (orc == CONFACK && /* Good CI */ 01131 rc != CONFACK) { /* but prior CI wasnt? */ 01132 continue; /* Don't send this one */ 01133 } 01134 01135 if (orc == CONFNAK) { /* Nak this CI? */ 01136 if (reject_if_disagree) { /* Getting fed up with sending NAKs? */ 01137 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n")); 01138 orc = CONFREJ; /* Get tough if so */ 01139 } else { 01140 if (rc == CONFREJ) { /* Rejecting prior CI? */ 01141 continue; /* Don't send this one */ 01142 } 01143 if (rc == CONFACK) { /* Ack'd all prior CIs? */ 01144 rc = CONFNAK; /* Not anymore... */ 01145 ucp = inp; /* Backup */ 01146 } 01147 } 01148 } 01149 01150 if (orc == CONFREJ && /* Reject this CI */ 01151 rc != CONFREJ) { /* but no prior ones? */ 01152 rc = CONFREJ; 01153 ucp = inp; /* Backup */ 01154 } 01155 01156 /* Need to move CI? */ 01157 if (ucp != cip) { 01158 BCOPY(cip, ucp, cilen); /* Move it */ 01159 } 01160 01161 /* Update output pointer */ 01162 INCPTR(cilen, ucp); 01163 } 01164 01165 /* 01166 * If we aren't rejecting this packet, and we want to negotiate 01167 * their address, and they didn't send their address, then we 01168 * send a NAK with a CI_ADDR option appended. We assume the 01169 * input buffer is long enough that we can append the extra 01170 * option safely. 01171 */ 01172 if (rc != CONFREJ && !ho->neg_addr && 01173 wo->req_addr && !reject_if_disagree) { 01174 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n")); 01175 if (rc == CONFACK) { 01176 rc = CONFNAK; 01177 ucp = inp; /* reset pointer */ 01178 wo->req_addr = 0; /* don't ask again */ 01179 } 01180 PUTCHAR(CI_ADDR, ucp); 01181 PUTCHAR(CILEN_ADDR, ucp); 01182 tl = ntohl(wo->hisaddr); 01183 PUTLONG(tl, ucp); 01184 } 01185 01186 *len = (int)(ucp - inp); /* Compute output length */ 01187 IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc))); 01188 return (rc); /* Return final code */ 01189 } 01190 01191 01192 #if 0 01193 /* 01194 * ip_check_options - check that any IP-related options are OK, 01195 * and assign appropriate defaults. 01196 */ 01197 static void 01198 ip_check_options(u_long localAddr) 01199 { 01200 ipcp_options *wo = &ipcp_wantoptions[0]; 01201 01202 /* 01203 * Load our default IP address but allow the remote host to give us 01204 * a new address. 01205 */ 01206 if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) { 01207 wo->accept_local = 1; /* don't insist on this default value */ 01208 wo->ouraddr = htonl(localAddr); 01209 } 01210 } 01211 #endif 01212 01213 01214 /* 01215 * ipcp_up - IPCP has come UP. 01216 * 01217 * Configure the IP network interface appropriately and bring it up. 01218 */ 01219 static void 01220 ipcp_up(fsm *f) 01221 { 01222 u32_t mask; 01223 ipcp_options *ho = &ipcp_hisoptions[f->unit]; 01224 ipcp_options *go = &ipcp_gotoptions[f->unit]; 01225 ipcp_options *wo = &ipcp_wantoptions[f->unit]; 01226 01227 np_up(f->unit, PPP_IP); 01228 IPCPDEBUG(LOG_INFO, ("ipcp: up\n")); 01229 01230 /* 01231 * We must have a non-zero IP address for both ends of the link. 01232 */ 01233 if (!ho->neg_addr) { 01234 ho->hisaddr = wo->hisaddr; 01235 } 01236 01237 if (ho->hisaddr == 0) { 01238 #if 0 01239 IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n")); 01240 ipcp_close(f->unit, "Could not determine remote IP address"); 01241 return; 01242 #else //Kludge 01243 ho->hisaddr = 0; //Set remote IP to 0.0.0.0, this is needed as most 3g providers do not advertise the remote IP to the user 01244 #endif 01245 } 01246 if (go->ouraddr == 0) { 01247 IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n")); 01248 ipcp_close(f->unit, "Could not determine local IP address"); 01249 return; 01250 } 01251 01252 if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { 01253 /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/ 01254 } 01255 01256 /* 01257 * Check that the peer is allowed to use the IP address it wants. 01258 */ 01259 if (!auth_ip_addr(f->unit, ho->hisaddr)) { 01260 IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n", 01261 inet_ntoa(ho->hisaddr))); 01262 ipcp_close(f->unit, "Unauthorized remote IP address"); 01263 return; 01264 } 01265 01266 /* set tcp compression */ 01267 sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); 01268 01269 /* 01270 * Set IP addresses and (if specified) netmask. 01271 */ 01272 mask = GetMask(go->ouraddr); 01273 01274 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) { 01275 IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n")); 01276 ipcp_close(f->unit, "Interface configuration failed"); 01277 return; 01278 } 01279 01280 /* bring the interface up for IP */ 01281 if (!sifup(f->unit)) { 01282 IPCPDEBUG(LOG_WARNING, ("sifup failed\n")); 01283 ipcp_close(f->unit, "Interface configuration failed"); 01284 return; 01285 } 01286 01287 sifnpmode(f->unit, PPP_IP, NPMODE_PASS); 01288 01289 /* assign a default route through the interface if required */ 01290 if (ipcp_wantoptions[f->unit].default_route) { 01291 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) { 01292 default_route_set[f->unit] = 1; 01293 } 01294 } 01295 01296 IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr))); 01297 IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr))); 01298 if (go->dnsaddr[0]) { 01299 IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); 01300 } 01301 if (go->dnsaddr[1]) { 01302 IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); 01303 } 01304 } 01305 01306 01307 /* 01308 * ipcp_down - IPCP has gone DOWN. 01309 * 01310 * Take the IP network interface down, clear its addresses 01311 * and delete routes through it. 01312 */ 01313 static void 01314 ipcp_down(fsm *f) 01315 { 01316 IPCPDEBUG(LOG_INFO, ("ipcp: down\n")); 01317 np_down(f->unit, PPP_IP); 01318 sifvjcomp(f->unit, 0, 0, 0); 01319 01320 sifdown(f->unit); 01321 ipcp_clear_addrs(f->unit); 01322 } 01323 01324 01325 /* 01326 * ipcp_clear_addrs() - clear the interface addresses, routes, etc. 01327 */ 01328 static void 01329 ipcp_clear_addrs(int unit) 01330 { 01331 u32_t ouraddr, hisaddr; 01332 01333 ouraddr = ipcp_gotoptions[unit].ouraddr; 01334 hisaddr = ipcp_hisoptions[unit].hisaddr; 01335 if (default_route_set[unit]) { 01336 cifdefaultroute(unit, ouraddr, hisaddr); 01337 default_route_set[unit] = 0; 01338 } 01339 cifaddr(unit, ouraddr, hisaddr); 01340 } 01341 01342 01343 /* 01344 * ipcp_finished - possibly shut down the lower layers. 01345 */ 01346 static void 01347 ipcp_finished(fsm *f) 01348 { 01349 np_finished(f->unit, PPP_IP); 01350 } 01351 01352 #if PPP_ADDITIONAL_CALLBACKS 01353 static int 01354 ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) 01355 { 01356 LWIP_UNUSED_ARG(p); 01357 LWIP_UNUSED_ARG(plen); 01358 LWIP_UNUSED_ARG(printer); 01359 LWIP_UNUSED_ARG(arg); 01360 return 0; 01361 } 01362 01363 /* 01364 * ip_active_pkt - see if this IP packet is worth bringing the link up for. 01365 * We don't bring the link up for IP fragments or for TCP FIN packets 01366 * with no data. 01367 */ 01368 #define IP_HDRLEN 20 /* bytes */ 01369 #define IP_OFFMASK 0x1fff 01370 #define IPPROTO_TCP 6 01371 #define TCP_HDRLEN 20 01372 #define TH_FIN 0x01 01373 01374 /* 01375 * We use these macros because the IP header may be at an odd address, 01376 * and some compilers might use word loads to get th_off or ip_hl. 01377 */ 01378 01379 #define net_short(x) (((x)[0] << 8) + (x)[1]) 01380 #define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) 01381 #define get_ipoff(x) net_short((unsigned char *)(x) + 6) 01382 #define get_ipproto(x) (((unsigned char *)(x))[9]) 01383 #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) 01384 #define get_tcpflags(x) (((unsigned char *)(x))[13]) 01385 01386 static int 01387 ip_active_pkt(u_char *pkt, int len) 01388 { 01389 u_char *tcp; 01390 int hlen; 01391 01392 len -= PPP_HDRLEN; 01393 pkt += PPP_HDRLEN; 01394 if (len < IP_HDRLEN) { 01395 return 0; 01396 } 01397 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) { 01398 return 0; 01399 } 01400 if (get_ipproto(pkt) != IPPROTO_TCP) { 01401 return 1; 01402 } 01403 hlen = get_iphl(pkt) * 4; 01404 if (len < hlen + TCP_HDRLEN) { 01405 return 0; 01406 } 01407 tcp = pkt + hlen; 01408 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) { 01409 return 0; 01410 } 01411 return 1; 01412 } 01413 #endif /* PPP_ADDITIONAL_CALLBACKS */ 01414 01415 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 11:29:37 by
