NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
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 #ifdef __PPP_STRICT_IMPL__ //DG : Kludge for bad 3g providers PPP impl 01237 if (ho->hisaddr == 0) { 01238 IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n")); 01239 ipcp_close(f->unit, "Could not determine remote IP address"); 01240 return; 01241 } 01242 #endif 01243 if (go->ouraddr == 0) { 01244 IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n")); 01245 ipcp_close(f->unit, "Could not determine local IP address"); 01246 return; 01247 } 01248 01249 if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { 01250 /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/ 01251 } 01252 01253 /* 01254 * Check that the peer is allowed to use the IP address it wants. 01255 */ 01256 if (!auth_ip_addr(f->unit, ho->hisaddr)) { 01257 IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n", 01258 inet_ntoa(ho->hisaddr))); 01259 ipcp_close(f->unit, "Unauthorized remote IP address"); 01260 return; 01261 } 01262 01263 /* set tcp compression */ 01264 sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); 01265 01266 /* 01267 * Set IP addresses and (if specified) netmask. 01268 */ 01269 mask = GetMask(go->ouraddr); 01270 01271 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) { 01272 IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n")); 01273 ipcp_close(f->unit, "Interface configuration failed"); 01274 return; 01275 } 01276 01277 /* bring the interface up for IP */ 01278 if (!sifup(f->unit)) { 01279 IPCPDEBUG(LOG_WARNING, ("sifup failed\n")); 01280 ipcp_close(f->unit, "Interface configuration failed"); 01281 return; 01282 } 01283 01284 sifnpmode(f->unit, PPP_IP, NPMODE_PASS); 01285 01286 /* assign a default route through the interface if required */ 01287 if (ipcp_wantoptions[f->unit].default_route) { 01288 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) { 01289 default_route_set[f->unit] = 1; 01290 } 01291 } 01292 01293 IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr))); 01294 IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr))); 01295 if (go->dnsaddr[0]) { 01296 IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); 01297 } 01298 if (go->dnsaddr[1]) { 01299 IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); 01300 } 01301 } 01302 01303 01304 /* 01305 * ipcp_down - IPCP has gone DOWN. 01306 * 01307 * Take the IP network interface down, clear its addresses 01308 * and delete routes through it. 01309 */ 01310 static void 01311 ipcp_down(fsm *f) 01312 { 01313 IPCPDEBUG(LOG_INFO, ("ipcp: down\n")); 01314 np_down(f->unit, PPP_IP); 01315 sifvjcomp(f->unit, 0, 0, 0); 01316 01317 sifdown(f->unit); 01318 ipcp_clear_addrs(f->unit); 01319 } 01320 01321 01322 /* 01323 * ipcp_clear_addrs() - clear the interface addresses, routes, etc. 01324 */ 01325 static void 01326 ipcp_clear_addrs(int unit) 01327 { 01328 u32_t ouraddr, hisaddr; 01329 01330 ouraddr = ipcp_gotoptions[unit].ouraddr; 01331 hisaddr = ipcp_hisoptions[unit].hisaddr; 01332 if (default_route_set[unit]) { 01333 cifdefaultroute(unit, ouraddr, hisaddr); 01334 default_route_set[unit] = 0; 01335 } 01336 cifaddr(unit, ouraddr, hisaddr); 01337 } 01338 01339 01340 /* 01341 * ipcp_finished - possibly shut down the lower layers. 01342 */ 01343 static void 01344 ipcp_finished(fsm *f) 01345 { 01346 np_finished(f->unit, PPP_IP); 01347 } 01348 01349 #if PPP_ADDITIONAL_CALLBACKS 01350 static int 01351 ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) 01352 { 01353 LWIP_UNUSED_ARG(p); 01354 LWIP_UNUSED_ARG(plen); 01355 LWIP_UNUSED_ARG(printer); 01356 LWIP_UNUSED_ARG(arg); 01357 return 0; 01358 } 01359 01360 /* 01361 * ip_active_pkt - see if this IP packet is worth bringing the link up for. 01362 * We don't bring the link up for IP fragments or for TCP FIN packets 01363 * with no data. 01364 */ 01365 #define IP_HDRLEN 20 /* bytes */ 01366 #define IP_OFFMASK 0x1fff 01367 #define IPPROTO_TCP 6 01368 #define TCP_HDRLEN 20 01369 #define TH_FIN 0x01 01370 01371 /* 01372 * We use these macros because the IP header may be at an odd address, 01373 * and some compilers might use word loads to get th_off or ip_hl. 01374 */ 01375 01376 #define net_short(x) (((x)[0] << 8) + (x)[1]) 01377 #define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) 01378 #define get_ipoff(x) net_short((unsigned char *)(x) + 6) 01379 #define get_ipproto(x) (((unsigned char *)(x))[9]) 01380 #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) 01381 #define get_tcpflags(x) (((unsigned char *)(x))[13]) 01382 01383 static int 01384 ip_active_pkt(u_char *pkt, int len) 01385 { 01386 u_char *tcp; 01387 int hlen; 01388 01389 len -= PPP_HDRLEN; 01390 pkt += PPP_HDRLEN; 01391 if (len < IP_HDRLEN) { 01392 return 0; 01393 } 01394 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) { 01395 return 0; 01396 } 01397 if (get_ipproto(pkt) != IPPROTO_TCP) { 01398 return 1; 01399 } 01400 hlen = get_iphl(pkt) * 4; 01401 if (len < hlen + TCP_HDRLEN) { 01402 return 0; 01403 } 01404 tcp = pkt + hlen; 01405 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) { 01406 return 0; 01407 } 01408 return 1; 01409 } 01410 #endif /* PPP_ADDITIONAL_CALLBACKS */ 01411 01412 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 11:52:57 by
![doxygen](doxygen.png)