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.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
lwip_ipcp.c
00001 /* 00002 * ipcp.c - PPP IP Control Protocol. 00003 * 00004 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * 3. The name "Carnegie Mellon University" must not be used to 00019 * endorse or promote products derived from this software without 00020 * prior written permission. For permission or any legal 00021 * details, please contact 00022 * Office of Technology Transfer 00023 * Carnegie Mellon University 00024 * 5000 Forbes Avenue 00025 * Pittsburgh, PA 15213-3890 00026 * (412) 268-4387, fax: (412) 268-7395 00027 * tech-transfer@andrew.cmu.edu 00028 * 00029 * 4. Redistributions of any form whatsoever must retain the following 00030 * acknowledgment: 00031 * "This product includes software developed by Computing Services 00032 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 00033 * 00034 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 00035 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00036 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 00037 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00038 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 00039 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 00040 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00041 */ 00042 00043 #include "netif/ppp/ppp_opts.h" 00044 #if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00045 00046 /* 00047 * @todo: 00048 */ 00049 00050 #if 0 /* UNUSED */ 00051 #include <stdio.h> 00052 #include <string.h> 00053 #include <stdlib.h> 00054 #include <netdb.h> 00055 #include <sys/param.h> 00056 #include <sys/types.h> 00057 #include <sys/socket.h> 00058 #include <netinet/in.h> 00059 #include <arpa/inet.h> 00060 #endif /* UNUSED */ 00061 00062 #include "netif/ppp/ppp_impl.h" 00063 00064 #include "netif/ppp/fsm.h" 00065 #include "netif/ppp/ipcp.h" 00066 00067 #if 0 /* UNUSED */ 00068 /* global vars */ 00069 u32_t netmask = 0; /* IP netmask to set on interface */ 00070 #endif /* UNUSED */ 00071 00072 #if 0 /* UNUSED */ 00073 bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ 00074 #endif /* UNUSED */ 00075 00076 #if 0 /* moved to ppp_settings */ 00077 bool noremoteip = 0; /* Let him have no IP address */ 00078 #endif /* moved to ppp_setting */ 00079 00080 #if 0 /* UNUSED */ 00081 /* Hook for a plugin to know when IP protocol has come up */ 00082 void (*ip_up_hook) (void) = NULL; 00083 00084 /* Hook for a plugin to know when IP protocol has come down */ 00085 void (*ip_down_hook) (void) = NULL; 00086 00087 /* Hook for a plugin to choose the remote IP address */ 00088 void (*ip_choose_hook) (u32_t *) = NULL; 00089 #endif /* UNUSED */ 00090 00091 #if PPP_NOTIFY 00092 /* Notifiers for when IPCP goes up and down */ 00093 struct notifier *ip_up_notifier = NULL; 00094 struct notifier *ip_down_notifier = NULL; 00095 #endif /* PPP_NOTIFY */ 00096 00097 /* local vars */ 00098 #if 0 /* moved to ppp_pcb */ 00099 static int default_route_set[NUM_PPP]; /* Have set up a default route */ 00100 static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ 00101 static int ipcp_is_up; /* have called np_up() */ 00102 static int ipcp_is_open; /* haven't called np_finished() */ 00103 static bool ask_for_local; /* request our address from peer */ 00104 #endif /* moved to ppp_pcb */ 00105 #if 0 /* UNUSED */ 00106 static char vj_value[8]; /* string form of vj option value */ 00107 static char netmask_str[20]; /* string form of netmask value */ 00108 #endif /* UNUSED */ 00109 00110 /* 00111 * Callbacks for fsm code. (CI = Configuration Information) 00112 */ 00113 static void ipcp_resetci(fsm *f); /* Reset our CI */ 00114 static int ipcp_cilen(fsm *f); /* Return length of our CI */ 00115 static void ipcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ 00116 static int ipcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ 00117 static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject);/* Peer nak'd our CI */ 00118 static int ipcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ 00119 static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ 00120 static void ipcp_up(fsm *f); /* We're UP */ 00121 static void ipcp_down(fsm *f); /* We're DOWN */ 00122 static void ipcp_finished(fsm *f); /* Don't need lower layer */ 00123 00124 static const fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ 00125 ipcp_resetci, /* Reset our Configuration Information */ 00126 ipcp_cilen, /* Length of our Configuration Information */ 00127 ipcp_addci, /* Add our Configuration Information */ 00128 ipcp_ackci, /* ACK our Configuration Information */ 00129 ipcp_nakci, /* NAK our Configuration Information */ 00130 ipcp_rejci, /* Reject our Configuration Information */ 00131 ipcp_reqci, /* Request peer's Configuration Information */ 00132 ipcp_up, /* Called when fsm reaches OPENED state */ 00133 ipcp_down, /* Called when fsm leaves OPENED state */ 00134 NULL, /* Called when we want the lower layer up */ 00135 ipcp_finished, /* Called when we want the lower layer down */ 00136 NULL, /* Called when Protocol-Reject received */ 00137 NULL, /* Retransmission is necessary */ 00138 NULL, /* Called to handle protocol-specific codes */ 00139 "IPCP" /* String name of protocol */ 00140 }; 00141 00142 /* 00143 * Command-line options. 00144 */ 00145 #if PPP_OPTIONS 00146 static int setvjslots (char **); 00147 static int setdnsaddr (char **); 00148 static int setwinsaddr (char **); 00149 static int setnetmask (char **); 00150 int setipaddr (char *, char **, int); 00151 00152 static void printipaddr (option_t *, void (*)(void *, char *,...),void *); 00153 00154 static option_t ipcp_option_list[] = { 00155 { "noip", o_bool, &ipcp_protent.enabled_flag, 00156 "Disable IP and IPCP" }, 00157 { "-ip", o_bool, &ipcp_protent.enabled_flag, 00158 "Disable IP and IPCP", OPT_ALIAS }, 00159 00160 { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, 00161 "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, 00162 { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, 00163 "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, 00164 &ipcp_allowoptions[0].neg_vj }, 00165 00166 { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, 00167 "Disable VJ connection-ID compression", OPT_A2CLR, 00168 &ipcp_allowoptions[0].cflag }, 00169 { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, 00170 "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, 00171 &ipcp_allowoptions[0].cflag }, 00172 00173 { "vj-max-slots", o_special, (void *)setvjslots, 00174 "Set maximum VJ header slots", 00175 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, 00176 00177 { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, 00178 "Accept peer's address for us", 1 }, 00179 { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, 00180 "Accept peer's address for it", 1 }, 00181 00182 { "ipparam", o_string, &ipparam, 00183 "Set ip script parameter", OPT_PRIO }, 00184 00185 { "noipdefault", o_bool, &disable_defaultip, 00186 "Don't use name for default IP adrs", 1 }, 00187 00188 { "ms-dns", 1, (void *)setdnsaddr, 00189 "DNS address for the peer's use" }, 00190 { "ms-wins", 1, (void *)setwinsaddr, 00191 "Nameserver for SMB over TCP/IP for peer" }, 00192 00193 { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, 00194 "Set timeout for IPCP", OPT_PRIO }, 00195 { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, 00196 "Set max #xmits for term-reqs", OPT_PRIO }, 00197 { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, 00198 "Set max #xmits for conf-reqs", OPT_PRIO }, 00199 { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, 00200 "Set max #conf-naks for IPCP", OPT_PRIO }, 00201 00202 { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, 00203 "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, 00204 { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, 00205 "disable defaultroute option", OPT_A2CLR, 00206 &ipcp_wantoptions[0].default_route }, 00207 { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, 00208 "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, 00209 &ipcp_wantoptions[0].default_route }, 00210 00211 { "replacedefaultroute", o_bool, 00212 &ipcp_wantoptions[0].replace_default_route, 00213 "Replace default route", 1 00214 }, 00215 { "noreplacedefaultroute", o_bool, 00216 &ipcp_allowoptions[0].replace_default_route, 00217 "Never replace default route", OPT_A2COPY, 00218 &ipcp_wantoptions[0].replace_default_route }, 00219 { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, 00220 "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, 00221 { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, 00222 "disable proxyarp option", OPT_A2CLR, 00223 &ipcp_wantoptions[0].proxy_arp }, 00224 { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, 00225 "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, 00226 &ipcp_wantoptions[0].proxy_arp }, 00227 00228 { "usepeerdns", o_bool, &usepeerdns, 00229 "Ask peer for DNS address(es)", 1 }, 00230 00231 { "netmask", o_special, (void *)setnetmask, 00232 "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, 00233 00234 { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs, 00235 "Disable old-style IP-Addresses usage", OPT_A2CLR, 00236 &ipcp_allowoptions[0].old_addrs }, 00237 { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr, 00238 "Disable IP-Address usage", OPT_A2CLR, 00239 &ipcp_allowoptions[0].neg_addr }, 00240 00241 { "noremoteip", o_bool, &noremoteip, 00242 "Allow peer to have no IP address", 1 }, 00243 00244 { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr, 00245 "Don't send our IP address to peer", OPT_A2CLR, 00246 &ipcp_wantoptions[0].old_addrs}, 00247 00248 { "IP addresses", o_wild, (void *) &setipaddr, 00249 "set local and remote IP addresses", 00250 OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, 00251 00252 { NULL } 00253 }; 00254 #endif /* PPP_OPTIONS */ 00255 00256 /* 00257 * Protocol entry points from main code. 00258 */ 00259 static void ipcp_init(ppp_pcb *pcb); 00260 static void ipcp_open(ppp_pcb *pcb); 00261 static void ipcp_close(ppp_pcb *pcb, const char *reason); 00262 static void ipcp_lowerup(ppp_pcb *pcb); 00263 static void ipcp_lowerdown(ppp_pcb *pcb); 00264 static void ipcp_input(ppp_pcb *pcb, u_char *p, int len); 00265 static void ipcp_protrej(ppp_pcb *pcb); 00266 #if PRINTPKT_SUPPORT 00267 static int ipcp_printpkt(const u_char *p, int plen, 00268 void (*printer) (void *, const char *, ...), void *arg); 00269 #endif /* PRINTPKT_SUPPORT */ 00270 #if PPP_OPTIONS 00271 static void ip_check_options (void); 00272 #endif /* PPP_OPTIONS */ 00273 #if DEMAND_SUPPORT 00274 static int ip_demand_conf (int); 00275 static int ip_active_pkt (u_char *, int); 00276 #endif /* DEMAND_SUPPORT */ 00277 #if 0 /* UNUSED */ 00278 static void create_resolv (u32_t, u32_t); 00279 #endif /* UNUSED */ 00280 00281 const struct protent ipcp_protent = { 00282 PPP_IPCP, 00283 ipcp_init, 00284 ipcp_input, 00285 ipcp_protrej, 00286 ipcp_lowerup, 00287 ipcp_lowerdown, 00288 ipcp_open, 00289 ipcp_close, 00290 #if PRINTPKT_SUPPORT 00291 ipcp_printpkt, 00292 #endif /* PRINTPKT_SUPPORT */ 00293 #if PPP_DATAINPUT 00294 NULL, 00295 #endif /* PPP_DATAINPUT */ 00296 #if PRINTPKT_SUPPORT 00297 "IPCP", 00298 "IP", 00299 #endif /* PRINTPKT_SUPPORT */ 00300 #if PPP_OPTIONS 00301 ipcp_option_list, 00302 ip_check_options, 00303 #endif /* PPP_OPTIONS */ 00304 #if DEMAND_SUPPORT 00305 ip_demand_conf, 00306 ip_active_pkt 00307 #endif /* DEMAND_SUPPORT */ 00308 }; 00309 00310 static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute); 00311 00312 /* 00313 * Lengths of configuration options. 00314 */ 00315 #define CILEN_VOID 2 00316 #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ 00317 #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ 00318 #define CILEN_ADDR 6 /* new-style single address option */ 00319 #define CILEN_ADDRS 10 /* old-style dual address option */ 00320 00321 00322 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ 00323 (x) == CONFNAK ? "NAK" : "REJ") 00324 00325 #if 0 /* UNUSED, already defined by lwIP */ 00326 /* 00327 * Make a string representation of a network IP address. 00328 */ 00329 char * 00330 ip_ntoa(ipaddr) 00331 u32_t ipaddr; 00332 { 00333 static char b[64]; 00334 00335 slprintf(b, sizeof(b), "%I", ipaddr); 00336 return b; 00337 } 00338 #endif /* UNUSED, already defined by lwIP */ 00339 00340 /* 00341 * Option parsing. 00342 */ 00343 #if PPP_OPTIONS 00344 /* 00345 * setvjslots - set maximum number of connection slots for VJ compression 00346 */ 00347 static int 00348 setvjslots(argv) 00349 char **argv; 00350 { 00351 int value; 00352 00353 /* FIXME: found what int_option() did */ 00354 #if PPP_OPTIONS 00355 if (!int_option(*argv, &value)) 00356 return 0; 00357 #endif /* PPP_OPTIONS */ 00358 00359 if (value < 2 || value > 16) { 00360 option_error("vj-max-slots value must be between 2 and 16"); 00361 return 0; 00362 } 00363 ipcp_wantoptions [0].maxslotindex = 00364 ipcp_allowoptions[0].maxslotindex = value - 1; 00365 slprintf(vj_value, sizeof(vj_value), "%d", value); 00366 return 1; 00367 } 00368 00369 /* 00370 * setdnsaddr - set the dns address(es) 00371 */ 00372 static int 00373 setdnsaddr(argv) 00374 char **argv; 00375 { 00376 u32_t dns; 00377 struct hostent *hp; 00378 00379 dns = inet_addr(*argv); 00380 if (dns == (u32_t) -1) { 00381 if ((hp = gethostbyname(*argv)) == NULL) { 00382 option_error("invalid address parameter '%s' for ms-dns option", 00383 *argv); 00384 return 0; 00385 } 00386 dns = *(u32_t *)hp->h_addr; 00387 } 00388 00389 /* We take the last 2 values given, the 2nd-last as the primary 00390 and the last as the secondary. If only one is given it 00391 becomes both primary and secondary. */ 00392 if (ipcp_allowoptions[0].dnsaddr[1] == 0) 00393 ipcp_allowoptions[0].dnsaddr[0] = dns; 00394 else 00395 ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; 00396 00397 /* always set the secondary address value. */ 00398 ipcp_allowoptions[0].dnsaddr[1] = dns; 00399 00400 return (1); 00401 } 00402 00403 /* 00404 * setwinsaddr - set the wins address(es) 00405 * This is primrarly used with the Samba package under UNIX or for pointing 00406 * the caller to the existing WINS server on a Windows NT platform. 00407 */ 00408 static int 00409 setwinsaddr(argv) 00410 char **argv; 00411 { 00412 u32_t wins; 00413 struct hostent *hp; 00414 00415 wins = inet_addr(*argv); 00416 if (wins == (u32_t) -1) { 00417 if ((hp = gethostbyname(*argv)) == NULL) { 00418 option_error("invalid address parameter '%s' for ms-wins option", 00419 *argv); 00420 return 0; 00421 } 00422 wins = *(u32_t *)hp->h_addr; 00423 } 00424 00425 /* We take the last 2 values given, the 2nd-last as the primary 00426 and the last as the secondary. If only one is given it 00427 becomes both primary and secondary. */ 00428 if (ipcp_allowoptions[0].winsaddr[1] == 0) 00429 ipcp_allowoptions[0].winsaddr[0] = wins; 00430 else 00431 ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; 00432 00433 /* always set the secondary address value. */ 00434 ipcp_allowoptions[0].winsaddr[1] = wins; 00435 00436 return (1); 00437 } 00438 00439 /* 00440 * setipaddr - Set the IP address 00441 * If doit is 0, the call is to check whether this option is 00442 * potentially an IP address specification. 00443 * Not static so that plugins can call it to set the addresses 00444 */ 00445 int 00446 setipaddr(arg, argv, doit) 00447 char *arg; 00448 char **argv; 00449 int doit; 00450 { 00451 struct hostent *hp; 00452 char *colon; 00453 u32_t local, remote; 00454 ipcp_options *wo = &ipcp_wantoptions[0]; 00455 static int prio_local = 0, prio_remote = 0; 00456 00457 /* 00458 * IP address pair separated by ":". 00459 */ 00460 if ((colon = strchr(arg, ':')) == NULL) 00461 return 0; 00462 if (!doit) 00463 return 1; 00464 00465 /* 00466 * If colon first character, then no local addr. 00467 */ 00468 if (colon != arg && option_priority >= prio_local) { 00469 *colon = '\0'; 00470 if ((local = inet_addr(arg)) == (u32_t) -1) { 00471 if ((hp = gethostbyname(arg)) == NULL) { 00472 option_error("unknown host: %s", arg); 00473 return 0; 00474 } 00475 local = *(u32_t *)hp->h_addr; 00476 } 00477 if (bad_ip_adrs(local)) { 00478 option_error("bad local IP address %s", ip_ntoa(local)); 00479 return 0; 00480 } 00481 if (local != 0) 00482 wo->ouraddr = local; 00483 *colon = ':'; 00484 prio_local = option_priority; 00485 } 00486 00487 /* 00488 * If colon last character, then no remote addr. 00489 */ 00490 if (*++colon != '\0' && option_priority >= prio_remote) { 00491 if ((remote = inet_addr(colon)) == (u32_t) -1) { 00492 if ((hp = gethostbyname(colon)) == NULL) { 00493 option_error("unknown host: %s", colon); 00494 return 0; 00495 } 00496 remote = *(u32_t *)hp->h_addr; 00497 if (remote_name[0] == 0) 00498 strlcpy(remote_name, colon, sizeof(remote_name)); 00499 } 00500 if (bad_ip_adrs(remote)) { 00501 option_error("bad remote IP address %s", ip_ntoa(remote)); 00502 return 0; 00503 } 00504 if (remote != 0) 00505 wo->hisaddr = remote; 00506 prio_remote = option_priority; 00507 } 00508 00509 return 1; 00510 } 00511 00512 static void 00513 printipaddr(opt, printer, arg) 00514 option_t *opt; 00515 void (*printer) (void *, char *, ...); 00516 void *arg; 00517 { 00518 ipcp_options *wo = &ipcp_wantoptions[0]; 00519 00520 if (wo->ouraddr != 0) 00521 printer(arg, "%I", wo->ouraddr); 00522 printer(arg, ":"); 00523 if (wo->hisaddr != 0) 00524 printer(arg, "%I", wo->hisaddr); 00525 } 00526 00527 /* 00528 * setnetmask - set the netmask to be used on the interface. 00529 */ 00530 static int 00531 setnetmask(argv) 00532 char **argv; 00533 { 00534 u32_t mask; 00535 int n; 00536 char *p; 00537 00538 /* 00539 * Unfortunately, if we use inet_addr, we can't tell whether 00540 * a result of all 1s is an error or a valid 255.255.255.255. 00541 */ 00542 p = *argv; 00543 n = parse_dotted_ip(p, &mask); 00544 00545 mask = htonl(mask); 00546 00547 if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { 00548 option_error("invalid netmask value '%s'", *argv); 00549 return 0; 00550 } 00551 00552 netmask = mask; 00553 slprintf(netmask_str, sizeof(netmask_str), "%I", mask); 00554 00555 return (1); 00556 } 00557 00558 int 00559 parse_dotted_ip(p, vp) 00560 char *p; 00561 u32_t *vp; 00562 { 00563 int n; 00564 u32_t v, b; 00565 char *endp, *p0 = p; 00566 00567 v = 0; 00568 for (n = 3;; --n) { 00569 b = strtoul(p, &endp, 0); 00570 if (endp == p) 00571 return 0; 00572 if (b > 255) { 00573 if (n < 3) 00574 return 0; 00575 /* accept e.g. 0xffffff00 */ 00576 *vp = b; 00577 return endp - p0; 00578 } 00579 v |= b << (n * 8); 00580 p = endp; 00581 if (n == 0) 00582 break; 00583 if (*p != '.') 00584 return 0; 00585 ++p; 00586 } 00587 *vp = v; 00588 return p - p0; 00589 } 00590 #endif /* PPP_OPTIONS */ 00591 00592 /* 00593 * ipcp_init - Initialize IPCP. 00594 */ 00595 static void ipcp_init(ppp_pcb *pcb) { 00596 fsm *f = &pcb->ipcp_fsm; 00597 00598 ipcp_options *wo = &pcb->ipcp_wantoptions; 00599 ipcp_options *ao = &pcb->ipcp_allowoptions; 00600 00601 f->pcb = pcb; 00602 f->protocol = PPP_IPCP; 00603 f->callbacks = &ipcp_callbacks; 00604 fsm_init(f); 00605 00606 /* 00607 * Some 3G modems use repeated IPCP NAKs as a way of stalling 00608 * until they can contact a server on the network, so we increase 00609 * the default number of NAKs we accept before we start treating 00610 * them as rejects. 00611 */ 00612 f->maxnakloops = 100; 00613 00614 #if 0 /* Not necessary, everything is cleared in ppp_new() */ 00615 memset(wo, 0, sizeof(*wo)); 00616 memset(ao, 0, sizeof(*ao)); 00617 #endif /* 0 */ 00618 00619 wo->neg_addr = wo->old_addrs = 1; 00620 #if VJ_SUPPORT 00621 wo->neg_vj = 1; 00622 wo->vj_protocol = IPCP_VJ_COMP; 00623 wo->maxslotindex = MAX_STATES - 1; /* really max index */ 00624 wo->cflag = 1; 00625 #endif /* VJ_SUPPORT */ 00626 00627 #if 0 /* UNUSED */ 00628 /* wanting default route by default */ 00629 wo->default_route = 1; 00630 #endif /* UNUSED */ 00631 00632 ao->neg_addr = ao->old_addrs = 1; 00633 #if VJ_SUPPORT 00634 /* max slots and slot-id compression are currently hardwired in */ 00635 /* ppp_if.c to 16 and 1, this needs to be changed (among other */ 00636 /* things) gmc */ 00637 00638 ao->neg_vj = 1; 00639 ao->maxslotindex = MAX_STATES - 1; 00640 ao->cflag = 1; 00641 #endif /* #if VJ_SUPPORT */ 00642 00643 #if 0 /* UNUSED */ 00644 /* 00645 * XXX These control whether the user may use the proxyarp 00646 * and defaultroute options. 00647 */ 00648 ao->proxy_arp = 1; 00649 ao->default_route = 1; 00650 #endif /* UNUSED */ 00651 } 00652 00653 00654 /* 00655 * ipcp_open - IPCP is allowed to come up. 00656 */ 00657 static void ipcp_open(ppp_pcb *pcb) { 00658 fsm *f = &pcb->ipcp_fsm; 00659 fsm_open(f); 00660 pcb->ipcp_is_open = 1; 00661 } 00662 00663 00664 /* 00665 * ipcp_close - Take IPCP down. 00666 */ 00667 static void ipcp_close(ppp_pcb *pcb, const char *reason) { 00668 fsm *f = &pcb->ipcp_fsm; 00669 fsm_close(f, reason); 00670 } 00671 00672 00673 /* 00674 * ipcp_lowerup - The lower layer is up. 00675 */ 00676 static void ipcp_lowerup(ppp_pcb *pcb) { 00677 fsm *f = &pcb->ipcp_fsm; 00678 fsm_lowerup(f); 00679 } 00680 00681 00682 /* 00683 * ipcp_lowerdown - The lower layer is down. 00684 */ 00685 static void ipcp_lowerdown(ppp_pcb *pcb) { 00686 fsm *f = &pcb->ipcp_fsm; 00687 fsm_lowerdown(f); 00688 } 00689 00690 00691 /* 00692 * ipcp_input - Input IPCP packet. 00693 */ 00694 static void ipcp_input(ppp_pcb *pcb, u_char *p, int len) { 00695 fsm *f = &pcb->ipcp_fsm; 00696 fsm_input(f, p, len); 00697 } 00698 00699 00700 /* 00701 * ipcp_protrej - A Protocol-Reject was received for IPCP. 00702 * 00703 * Pretend the lower layer went down, so we shut up. 00704 */ 00705 static void ipcp_protrej(ppp_pcb *pcb) { 00706 fsm *f = &pcb->ipcp_fsm; 00707 fsm_lowerdown(f); 00708 } 00709 00710 00711 /* 00712 * ipcp_resetci - Reset our CI. 00713 * Called by fsm_sconfreq, Send Configure Request. 00714 */ 00715 static void ipcp_resetci(fsm *f) { 00716 ppp_pcb *pcb = f->pcb; 00717 ipcp_options *wo = &pcb->ipcp_wantoptions; 00718 ipcp_options *go = &pcb->ipcp_gotoptions; 00719 ipcp_options *ao = &pcb->ipcp_allowoptions; 00720 00721 wo->req_addr = (wo->neg_addr || wo->old_addrs) && 00722 (ao->neg_addr || ao->old_addrs); 00723 if (wo->ouraddr == 0) 00724 wo->accept_local = 1; 00725 if (wo->hisaddr == 0) 00726 wo->accept_remote = 1; 00727 #if LWIP_DNS 00728 wo->req_dns1 = wo->req_dns2 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */ 00729 #endif /* LWIP_DNS */ 00730 *go = *wo; 00731 #if 0 /* UNUSED */ 00732 /* We don't need ask_for_local, this is only useful for setup which 00733 * can determine the local IP address from the system hostname. 00734 */ 00735 if (!ask_for_local) 00736 go->ouraddr = 0; 00737 #endif /* UNUSED */ 00738 #if 0 /* UNUSED */ 00739 if (ip_choose_hook) { 00740 ip_choose_hook(&wo->hisaddr); 00741 if (wo->hisaddr) { 00742 wo->accept_remote = 0; 00743 } 00744 } 00745 #endif /* UNUSED */ 00746 BZERO(&pcb->ipcp_hisoptions, sizeof(ipcp_options)); 00747 } 00748 00749 00750 /* 00751 * ipcp_cilen - Return length of our CI. 00752 * Called by fsm_sconfreq, Send Configure Request. 00753 */ 00754 static int ipcp_cilen(fsm *f) { 00755 ppp_pcb *pcb = f->pcb; 00756 ipcp_options *go = &pcb->ipcp_gotoptions; 00757 #if VJ_SUPPORT 00758 ipcp_options *wo = &pcb->ipcp_wantoptions; 00759 #endif /* VJ_SUPPORT */ 00760 ipcp_options *ho = &pcb->ipcp_hisoptions; 00761 00762 #define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) 00763 #if VJ_SUPPORT 00764 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) 00765 #endif /* VJ_SUPPORT */ 00766 #define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) 00767 #if LWIP_DNS 00768 #define LENCIDNS(neg) LENCIADDR(neg) 00769 #endif /* LWIP_DNS */ 00770 #if 0 /* UNUSED - WINS */ 00771 #define LENCIWINS(neg) LENCIADDR(neg) 00772 #endif /* UNUSED - WINS */ 00773 00774 /* 00775 * First see if we want to change our options to the old 00776 * forms because we have received old forms from the peer. 00777 */ 00778 if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) 00779 go->neg_addr = 0; 00780 00781 #if VJ_SUPPORT 00782 if (wo->neg_vj && !go->neg_vj && !go->old_vj) { 00783 /* try an older style of VJ negotiation */ 00784 /* use the old style only if the peer did */ 00785 if (ho->neg_vj && ho->old_vj) { 00786 go->neg_vj = 1; 00787 go->old_vj = 1; 00788 go->vj_protocol = ho->vj_protocol; 00789 } 00790 } 00791 #endif /* VJ_SUPPORT */ 00792 00793 return (LENCIADDRS(!go->neg_addr && go->old_addrs) + 00794 #if VJ_SUPPORT 00795 LENCIVJ(go->neg_vj, go->old_vj) + 00796 #endif /* VJ_SUPPORT */ 00797 LENCIADDR(go->neg_addr) + 00798 #if LWIP_DNS 00799 LENCIDNS(go->req_dns1) + 00800 LENCIDNS(go->req_dns2) + 00801 #endif /* LWIP_DNS */ 00802 #if 0 /* UNUSED - WINS */ 00803 LENCIWINS(go->winsaddr[0]) + 00804 LENCIWINS(go->winsaddr[1]) + 00805 #endif /* UNUSED - WINS */ 00806 0); 00807 } 00808 00809 00810 /* 00811 * ipcp_addci - Add our desired CIs to a packet. 00812 * Called by fsm_sconfreq, Send Configure Request. 00813 */ 00814 static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { 00815 ppp_pcb *pcb = f->pcb; 00816 ipcp_options *go = &pcb->ipcp_gotoptions; 00817 int len = *lenp; 00818 00819 #define ADDCIADDRS(opt, neg, val1, val2) \ 00820 if (neg) { \ 00821 if (len >= CILEN_ADDRS) { \ 00822 u32_t l; \ 00823 PUTCHAR(opt, ucp); \ 00824 PUTCHAR(CILEN_ADDRS, ucp); \ 00825 l = ntohl(val1); \ 00826 PUTLONG(l, ucp); \ 00827 l = ntohl(val2); \ 00828 PUTLONG(l, ucp); \ 00829 len -= CILEN_ADDRS; \ 00830 } else \ 00831 go->old_addrs = 0; \ 00832 } 00833 00834 #if VJ_SUPPORT 00835 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 00836 if (neg) { \ 00837 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 00838 if (len >= vjlen) { \ 00839 PUTCHAR(opt, ucp); \ 00840 PUTCHAR(vjlen, ucp); \ 00841 PUTSHORT(val, ucp); \ 00842 if (!old) { \ 00843 PUTCHAR(maxslotindex, ucp); \ 00844 PUTCHAR(cflag, ucp); \ 00845 } \ 00846 len -= vjlen; \ 00847 } else \ 00848 neg = 0; \ 00849 } 00850 #endif /* VJ_SUPPORT */ 00851 00852 #define ADDCIADDR(opt, neg, val) \ 00853 if (neg) { \ 00854 if (len >= CILEN_ADDR) { \ 00855 u32_t l; \ 00856 PUTCHAR(opt, ucp); \ 00857 PUTCHAR(CILEN_ADDR, ucp); \ 00858 l = ntohl(val); \ 00859 PUTLONG(l, ucp); \ 00860 len -= CILEN_ADDR; \ 00861 } else \ 00862 neg = 0; \ 00863 } 00864 00865 #if LWIP_DNS 00866 #define ADDCIDNS(opt, neg, addr) \ 00867 if (neg) { \ 00868 if (len >= CILEN_ADDR) { \ 00869 u32_t l; \ 00870 PUTCHAR(opt, ucp); \ 00871 PUTCHAR(CILEN_ADDR, ucp); \ 00872 l = ntohl(addr); \ 00873 PUTLONG(l, ucp); \ 00874 len -= CILEN_ADDR; \ 00875 } else \ 00876 neg = 0; \ 00877 } 00878 #endif /* LWIP_DNS */ 00879 00880 #if 0 /* UNUSED - WINS */ 00881 #define ADDCIWINS(opt, addr) \ 00882 if (addr) { \ 00883 if (len >= CILEN_ADDR) { \ 00884 u32_t l; \ 00885 PUTCHAR(opt, ucp); \ 00886 PUTCHAR(CILEN_ADDR, ucp); \ 00887 l = ntohl(addr); \ 00888 PUTLONG(l, ucp); \ 00889 len -= CILEN_ADDR; \ 00890 } else \ 00891 addr = 0; \ 00892 } 00893 #endif /* UNUSED - WINS */ 00894 00895 ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, 00896 go->hisaddr); 00897 00898 #if VJ_SUPPORT 00899 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 00900 go->maxslotindex, go->cflag); 00901 #endif /* VJ_SUPPORT */ 00902 00903 ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); 00904 00905 #if LWIP_DNS 00906 ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 00907 00908 ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 00909 #endif /* LWIP_DNS */ 00910 00911 #if 0 /* UNUSED - WINS */ 00912 ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); 00913 00914 ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); 00915 #endif /* UNUSED - WINS */ 00916 00917 *lenp -= len; 00918 } 00919 00920 00921 /* 00922 * ipcp_ackci - Ack our CIs. 00923 * Called by fsm_rconfack, Receive Configure ACK. 00924 * 00925 * Returns: 00926 * 0 - Ack was bad. 00927 * 1 - Ack was good. 00928 */ 00929 static int ipcp_ackci(fsm *f, u_char *p, int len) { 00930 ppp_pcb *pcb = f->pcb; 00931 ipcp_options *go = &pcb->ipcp_gotoptions; 00932 u_short cilen, citype; 00933 u32_t cilong; 00934 #if VJ_SUPPORT 00935 u_short cishort; 00936 u_char cimaxslotindex, cicflag; 00937 #endif /* VJ_SUPPORT */ 00938 00939 /* 00940 * CIs must be in exactly the same order that we sent... 00941 * Check packet length and CI length at each step. 00942 * If we find any deviations, then this packet is bad. 00943 */ 00944 00945 #define ACKCIADDRS(opt, neg, val1, val2) \ 00946 if (neg) { \ 00947 u32_t l; \ 00948 if ((len -= CILEN_ADDRS) < 0) \ 00949 goto bad; \ 00950 GETCHAR(citype, p); \ 00951 GETCHAR(cilen, p); \ 00952 if (cilen != CILEN_ADDRS || \ 00953 citype != opt) \ 00954 goto bad; \ 00955 GETLONG(l, p); \ 00956 cilong = htonl(l); \ 00957 if (val1 != cilong) \ 00958 goto bad; \ 00959 GETLONG(l, p); \ 00960 cilong = htonl(l); \ 00961 if (val2 != cilong) \ 00962 goto bad; \ 00963 } 00964 00965 #if VJ_SUPPORT 00966 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 00967 if (neg) { \ 00968 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 00969 if ((len -= vjlen) < 0) \ 00970 goto bad; \ 00971 GETCHAR(citype, p); \ 00972 GETCHAR(cilen, p); \ 00973 if (cilen != vjlen || \ 00974 citype != opt) \ 00975 goto bad; \ 00976 GETSHORT(cishort, p); \ 00977 if (cishort != val) \ 00978 goto bad; \ 00979 if (!old) { \ 00980 GETCHAR(cimaxslotindex, p); \ 00981 if (cimaxslotindex != maxslotindex) \ 00982 goto bad; \ 00983 GETCHAR(cicflag, p); \ 00984 if (cicflag != cflag) \ 00985 goto bad; \ 00986 } \ 00987 } 00988 #endif /* VJ_SUPPORT */ 00989 00990 #define ACKCIADDR(opt, neg, val) \ 00991 if (neg) { \ 00992 u32_t l; \ 00993 if ((len -= CILEN_ADDR) < 0) \ 00994 goto bad; \ 00995 GETCHAR(citype, p); \ 00996 GETCHAR(cilen, p); \ 00997 if (cilen != CILEN_ADDR || \ 00998 citype != opt) \ 00999 goto bad; \ 01000 GETLONG(l, p); \ 01001 cilong = htonl(l); \ 01002 if (val != cilong) \ 01003 goto bad; \ 01004 } 01005 01006 #if LWIP_DNS 01007 #define ACKCIDNS(opt, neg, addr) \ 01008 if (neg) { \ 01009 u32_t l; \ 01010 if ((len -= CILEN_ADDR) < 0) \ 01011 goto bad; \ 01012 GETCHAR(citype, p); \ 01013 GETCHAR(cilen, p); \ 01014 if (cilen != CILEN_ADDR || citype != opt) \ 01015 goto bad; \ 01016 GETLONG(l, p); \ 01017 cilong = htonl(l); \ 01018 if (addr != cilong) \ 01019 goto bad; \ 01020 } 01021 #endif /* LWIP_DNS */ 01022 01023 #if 0 /* UNUSED - WINS */ 01024 #define ACKCIWINS(opt, addr) \ 01025 if (addr) { \ 01026 u32_t l; \ 01027 if ((len -= CILEN_ADDR) < 0) \ 01028 goto bad; \ 01029 GETCHAR(citype, p); \ 01030 GETCHAR(cilen, p); \ 01031 if (cilen != CILEN_ADDR || citype != opt) \ 01032 goto bad; \ 01033 GETLONG(l, p); \ 01034 cilong = htonl(l); \ 01035 if (addr != cilong) \ 01036 goto bad; \ 01037 } 01038 #endif /* UNUSED - WINS */ 01039 01040 ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, 01041 go->hisaddr); 01042 01043 #if VJ_SUPPORT 01044 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 01045 go->maxslotindex, go->cflag); 01046 #endif /* VJ_SUPPORT */ 01047 01048 ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); 01049 01050 #if LWIP_DNS 01051 ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 01052 01053 ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 01054 #endif /* LWIP_DNS */ 01055 01056 #if 0 /* UNUSED - WINS */ 01057 ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); 01058 01059 ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); 01060 #endif /* UNUSED - WINS */ 01061 01062 /* 01063 * If there are any remaining CIs, then this packet is bad. 01064 */ 01065 if (len != 0) 01066 goto bad; 01067 return (1); 01068 01069 bad: 01070 IPCPDEBUG(("ipcp_ackci: received bad Ack!")); 01071 return (0); 01072 } 01073 01074 /* 01075 * ipcp_nakci - Peer has sent a NAK for some of our CIs. 01076 * This should not modify any state if the Nak is bad 01077 * or if IPCP is in the OPENED state. 01078 * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. 01079 * 01080 * Returns: 01081 * 0 - Nak was bad. 01082 * 1 - Nak was good. 01083 */ 01084 static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { 01085 ppp_pcb *pcb = f->pcb; 01086 ipcp_options *go = &pcb->ipcp_gotoptions; 01087 u_char citype, cilen, *next; 01088 #if VJ_SUPPORT 01089 u_char cimaxslotindex, cicflag; 01090 u_short cishort; 01091 #endif /* VJ_SUPPORT */ 01092 u32_t ciaddr1, ciaddr2, l; 01093 #if LWIP_DNS 01094 u32_t cidnsaddr; 01095 #endif /* LWIP_DNS */ 01096 ipcp_options no; /* options we've seen Naks for */ 01097 ipcp_options try_; /* options to request next time */ 01098 01099 BZERO(&no, sizeof(no)); 01100 try_ = *go; 01101 01102 /* 01103 * Any Nak'd CIs must be in exactly the same order that we sent. 01104 * Check packet length and CI length at each step. 01105 * If we find any deviations, then this packet is bad. 01106 */ 01107 #define NAKCIADDRS(opt, neg, code) \ 01108 if ((neg) && \ 01109 (cilen = p[1]) == CILEN_ADDRS && \ 01110 len >= cilen && \ 01111 p[0] == opt) { \ 01112 len -= cilen; \ 01113 INCPTR(2, p); \ 01114 GETLONG(l, p); \ 01115 ciaddr1 = htonl(l); \ 01116 GETLONG(l, p); \ 01117 ciaddr2 = htonl(l); \ 01118 no.old_addrs = 1; \ 01119 code \ 01120 } 01121 01122 #if VJ_SUPPORT 01123 #define NAKCIVJ(opt, neg, code) \ 01124 if (go->neg && \ 01125 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ 01126 len >= cilen && \ 01127 p[0] == opt) { \ 01128 len -= cilen; \ 01129 INCPTR(2, p); \ 01130 GETSHORT(cishort, p); \ 01131 no.neg = 1; \ 01132 code \ 01133 } 01134 #endif /* VJ_SUPPORT */ 01135 01136 #define NAKCIADDR(opt, neg, code) \ 01137 if (go->neg && \ 01138 (cilen = p[1]) == CILEN_ADDR && \ 01139 len >= cilen && \ 01140 p[0] == opt) { \ 01141 len -= cilen; \ 01142 INCPTR(2, p); \ 01143 GETLONG(l, p); \ 01144 ciaddr1 = htonl(l); \ 01145 no.neg = 1; \ 01146 code \ 01147 } 01148 01149 #if LWIP_DNS 01150 #define NAKCIDNS(opt, neg, code) \ 01151 if (go->neg && \ 01152 ((cilen = p[1]) == CILEN_ADDR) && \ 01153 len >= cilen && \ 01154 p[0] == opt) { \ 01155 len -= cilen; \ 01156 INCPTR(2, p); \ 01157 GETLONG(l, p); \ 01158 cidnsaddr = htonl(l); \ 01159 no.neg = 1; \ 01160 code \ 01161 } 01162 #endif /* LWIP_DNS */ 01163 01164 /* 01165 * Accept the peer's idea of {our,his} address, if different 01166 * from our idea, only if the accept_{local,remote} flag is set. 01167 */ 01168 NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, 01169 if (treat_as_reject) { 01170 try_.old_addrs = 0; 01171 } else { 01172 if (go->accept_local && ciaddr1) { 01173 /* take his idea of our address */ 01174 try_.ouraddr = ciaddr1; 01175 } 01176 if (go->accept_remote && ciaddr2) { 01177 /* take his idea of his address */ 01178 try_.hisaddr = ciaddr2; 01179 } 01180 } 01181 ); 01182 01183 #if VJ_SUPPORT 01184 /* 01185 * Accept the peer's value of maxslotindex provided that it 01186 * is less than what we asked for. Turn off slot-ID compression 01187 * if the peer wants. Send old-style compress-type option if 01188 * the peer wants. 01189 */ 01190 NAKCIVJ(CI_COMPRESSTYPE, neg_vj, 01191 if (treat_as_reject) { 01192 try_.neg_vj = 0; 01193 } else if (cilen == CILEN_VJ) { 01194 GETCHAR(cimaxslotindex, p); 01195 GETCHAR(cicflag, p); 01196 if (cishort == IPCP_VJ_COMP) { 01197 try_.old_vj = 0; 01198 if (cimaxslotindex < go->maxslotindex) 01199 try_.maxslotindex = cimaxslotindex; 01200 if (!cicflag) 01201 try_.cflag = 0; 01202 } else { 01203 try_.neg_vj = 0; 01204 } 01205 } else { 01206 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { 01207 try_.old_vj = 1; 01208 try_.vj_protocol = cishort; 01209 } else { 01210 try_.neg_vj = 0; 01211 } 01212 } 01213 ); 01214 #endif /* VJ_SUPPORT */ 01215 01216 NAKCIADDR(CI_ADDR, neg_addr, 01217 if (treat_as_reject) { 01218 try_.neg_addr = 0; 01219 try_.old_addrs = 0; 01220 } else if (go->accept_local && ciaddr1) { 01221 /* take his idea of our address */ 01222 try_.ouraddr = ciaddr1; 01223 } 01224 ); 01225 01226 #if LWIP_DNS 01227 NAKCIDNS(CI_MS_DNS1, req_dns1, 01228 if (treat_as_reject) { 01229 try_.req_dns1 = 0; 01230 } else { 01231 try_.dnsaddr[0] = cidnsaddr; 01232 } 01233 ); 01234 01235 NAKCIDNS(CI_MS_DNS2, req_dns2, 01236 if (treat_as_reject) { 01237 try_.req_dns2 = 0; 01238 } else { 01239 try_.dnsaddr[1] = cidnsaddr; 01240 } 01241 ); 01242 #endif /* #if LWIP_DNS */ 01243 01244 /* 01245 * There may be remaining CIs, if the peer is requesting negotiation 01246 * on an option that we didn't include in our request packet. 01247 * If they want to negotiate about IP addresses, we comply. 01248 * If they want us to ask for compression, we refuse. 01249 * If they want us to ask for ms-dns, we do that, since some 01250 * peers get huffy if we don't. 01251 */ 01252 while (len >= CILEN_VOID) { 01253 GETCHAR(citype, p); 01254 GETCHAR(cilen, p); 01255 if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) 01256 goto bad; 01257 next = p + cilen - 2; 01258 01259 switch (citype) { 01260 #if VJ_SUPPORT 01261 case CI_COMPRESSTYPE: 01262 if (go->neg_vj || no.neg_vj || 01263 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) 01264 goto bad; 01265 no.neg_vj = 1; 01266 break; 01267 #endif /* VJ_SUPPORT */ 01268 case CI_ADDRS: 01269 if ((!go->neg_addr && go->old_addrs) || no.old_addrs 01270 || cilen != CILEN_ADDRS) 01271 goto bad; 01272 try_.neg_addr = 0; 01273 GETLONG(l, p); 01274 ciaddr1 = htonl(l); 01275 if (ciaddr1 && go->accept_local) 01276 try_.ouraddr = ciaddr1; 01277 GETLONG(l, p); 01278 ciaddr2 = htonl(l); 01279 if (ciaddr2 && go->accept_remote) 01280 try_.hisaddr = ciaddr2; 01281 no.old_addrs = 1; 01282 break; 01283 case CI_ADDR: 01284 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) 01285 goto bad; 01286 try_.old_addrs = 0; 01287 GETLONG(l, p); 01288 ciaddr1 = htonl(l); 01289 if (ciaddr1 && go->accept_local) 01290 try_.ouraddr = ciaddr1; 01291 if (try_.ouraddr != 0) 01292 try_.neg_addr = 1; 01293 no.neg_addr = 1; 01294 break; 01295 #if LWIP_DNS 01296 case CI_MS_DNS1: 01297 if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) 01298 goto bad; 01299 GETLONG(l, p); 01300 try_.dnsaddr[0] = htonl(l); 01301 try_.req_dns1 = 1; 01302 no.req_dns1 = 1; 01303 break; 01304 case CI_MS_DNS2: 01305 if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) 01306 goto bad; 01307 GETLONG(l, p); 01308 try_.dnsaddr[1] = htonl(l); 01309 try_.req_dns2 = 1; 01310 no.req_dns2 = 1; 01311 break; 01312 #endif /* LWIP_DNS */ 01313 #if 0 /* UNUSED - WINS */ 01314 case CI_MS_WINS1: 01315 case CI_MS_WINS2: 01316 if (cilen != CILEN_ADDR) 01317 goto bad; 01318 GETLONG(l, p); 01319 ciaddr1 = htonl(l); 01320 if (ciaddr1) 01321 try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1; 01322 break; 01323 #endif /* UNUSED - WINS */ 01324 default: 01325 break; 01326 } 01327 p = next; 01328 } 01329 01330 /* 01331 * OK, the Nak is good. Now we can update state. 01332 * If there are any remaining options, we ignore them. 01333 */ 01334 if (f->state != PPP_FSM_OPENED) 01335 *go = try_; 01336 01337 return 1; 01338 01339 bad: 01340 IPCPDEBUG(("ipcp_nakci: received bad Nak!")); 01341 return 0; 01342 } 01343 01344 01345 /* 01346 * ipcp_rejci - Reject some of our CIs. 01347 * Callback from fsm_rconfnakrej. 01348 */ 01349 static int ipcp_rejci(fsm *f, u_char *p, int len) { 01350 ppp_pcb *pcb = f->pcb; 01351 ipcp_options *go = &pcb->ipcp_gotoptions; 01352 u_char cilen; 01353 #if VJ_SUPPORT 01354 u_char cimaxslotindex, ciflag; 01355 u_short cishort; 01356 #endif /* VJ_SUPPORT */ 01357 u32_t cilong; 01358 ipcp_options try_; /* options to request next time */ 01359 01360 try_ = *go; 01361 /* 01362 * Any Rejected CIs must be in exactly the same order that we sent. 01363 * Check packet length and CI length at each step. 01364 * If we find any deviations, then this packet is bad. 01365 */ 01366 #define REJCIADDRS(opt, neg, val1, val2) \ 01367 if ((neg) && \ 01368 (cilen = p[1]) == CILEN_ADDRS && \ 01369 len >= cilen && \ 01370 p[0] == opt) { \ 01371 u32_t l; \ 01372 len -= cilen; \ 01373 INCPTR(2, p); \ 01374 GETLONG(l, p); \ 01375 cilong = htonl(l); \ 01376 /* Check rejected value. */ \ 01377 if (cilong != val1) \ 01378 goto bad; \ 01379 GETLONG(l, p); \ 01380 cilong = htonl(l); \ 01381 /* Check rejected value. */ \ 01382 if (cilong != val2) \ 01383 goto bad; \ 01384 try_.old_addrs = 0; \ 01385 } 01386 01387 #if VJ_SUPPORT 01388 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ 01389 if (go->neg && \ 01390 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ 01391 len >= p[1] && \ 01392 p[0] == opt) { \ 01393 len -= p[1]; \ 01394 INCPTR(2, p); \ 01395 GETSHORT(cishort, p); \ 01396 /* Check rejected value. */ \ 01397 if (cishort != val) \ 01398 goto bad; \ 01399 if (!old) { \ 01400 GETCHAR(cimaxslotindex, p); \ 01401 if (cimaxslotindex != maxslot) \ 01402 goto bad; \ 01403 GETCHAR(ciflag, p); \ 01404 if (ciflag != cflag) \ 01405 goto bad; \ 01406 } \ 01407 try_.neg = 0; \ 01408 } 01409 #endif /* VJ_SUPPORT */ 01410 01411 #define REJCIADDR(opt, neg, val) \ 01412 if (go->neg && \ 01413 (cilen = p[1]) == CILEN_ADDR && \ 01414 len >= cilen && \ 01415 p[0] == opt) { \ 01416 u32_t l; \ 01417 len -= cilen; \ 01418 INCPTR(2, p); \ 01419 GETLONG(l, p); \ 01420 cilong = htonl(l); \ 01421 /* Check rejected value. */ \ 01422 if (cilong != val) \ 01423 goto bad; \ 01424 try_.neg = 0; \ 01425 } 01426 01427 #if LWIP_DNS 01428 #define REJCIDNS(opt, neg, dnsaddr) \ 01429 if (go->neg && \ 01430 ((cilen = p[1]) == CILEN_ADDR) && \ 01431 len >= cilen && \ 01432 p[0] == opt) { \ 01433 u32_t l; \ 01434 len -= cilen; \ 01435 INCPTR(2, p); \ 01436 GETLONG(l, p); \ 01437 cilong = htonl(l); \ 01438 /* Check rejected value. */ \ 01439 if (cilong != dnsaddr) \ 01440 goto bad; \ 01441 try_.neg = 0; \ 01442 } 01443 #endif /* LWIP_DNS */ 01444 01445 #if 0 /* UNUSED - WINS */ 01446 #define REJCIWINS(opt, addr) \ 01447 if (addr && \ 01448 ((cilen = p[1]) == CILEN_ADDR) && \ 01449 len >= cilen && \ 01450 p[0] == opt) { \ 01451 u32_t l; \ 01452 len -= cilen; \ 01453 INCPTR(2, p); \ 01454 GETLONG(l, p); \ 01455 cilong = htonl(l); \ 01456 /* Check rejected value. */ \ 01457 if (cilong != addr) \ 01458 goto bad; \ 01459 try_.winsaddr[opt == CI_MS_WINS2] = 0; \ 01460 } 01461 #endif /* UNUSED - WINS */ 01462 01463 REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, 01464 go->ouraddr, go->hisaddr); 01465 01466 #if VJ_SUPPORT 01467 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, 01468 go->maxslotindex, go->cflag); 01469 #endif /* VJ_SUPPORT */ 01470 01471 REJCIADDR(CI_ADDR, neg_addr, go->ouraddr); 01472 01473 #if LWIP_DNS 01474 REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); 01475 01476 REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); 01477 #endif /* LWIP_DNS */ 01478 01479 #if 0 /* UNUSED - WINS */ 01480 REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); 01481 01482 REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); 01483 #endif /* UNUSED - WINS */ 01484 01485 /* 01486 * If there are any remaining CIs, then this packet is bad. 01487 */ 01488 if (len != 0) 01489 goto bad; 01490 /* 01491 * Now we can update state. 01492 */ 01493 if (f->state != PPP_FSM_OPENED) 01494 *go = try_; 01495 return 1; 01496 01497 bad: 01498 IPCPDEBUG(("ipcp_rejci: received bad Reject!")); 01499 return 0; 01500 } 01501 01502 01503 /* 01504 * ipcp_reqci - Check the peer's requested CIs and send appropriate response. 01505 * Callback from fsm_rconfreq, Receive Configure Request 01506 * 01507 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified 01508 * appropriately. If reject_if_disagree is non-zero, doesn't return 01509 * CONFNAK; returns CONFREJ if it can't return CONFACK. 01510 * 01511 * inp = Requested CIs 01512 * len = Length of requested CIs 01513 */ 01514 static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { 01515 ppp_pcb *pcb = f->pcb; 01516 ipcp_options *wo = &pcb->ipcp_wantoptions; 01517 ipcp_options *ho = &pcb->ipcp_hisoptions; 01518 ipcp_options *ao = &pcb->ipcp_allowoptions; 01519 u_char *cip, *next; /* Pointer to current and next CIs */ 01520 u_short cilen, citype; /* Parsed len, type */ 01521 #if VJ_SUPPORT 01522 u_short cishort; /* Parsed short value */ 01523 #endif /* VJ_SUPPORT */ 01524 u32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ 01525 int rc = CONFACK; /* Final packet return code */ 01526 int orc; /* Individual option return code */ 01527 u_char *p; /* Pointer to next char to parse */ 01528 u_char *ucp = inp; /* Pointer to current output char */ 01529 int l = *len; /* Length left */ 01530 #if VJ_SUPPORT 01531 u_char maxslotindex, cflag; 01532 #endif /* VJ_SUPPORT */ 01533 #if LWIP_DNS 01534 int d; 01535 #endif /* LWIP_DNS */ 01536 01537 /* 01538 * Reset all his options. 01539 */ 01540 BZERO(ho, sizeof(*ho)); 01541 01542 /* 01543 * Process all his options. 01544 */ 01545 next = inp; 01546 while (l) { 01547 orc = CONFACK; /* Assume success */ 01548 cip = p = next; /* Remember begining of CI */ 01549 if (l < 2 || /* Not enough data for CI header or */ 01550 p[1] < 2 || /* CI length too small or */ 01551 p[1] > l) { /* CI length too big? */ 01552 IPCPDEBUG(("ipcp_reqci: bad CI length!")); 01553 orc = CONFREJ; /* Reject bad CI */ 01554 cilen = l; /* Reject till end of packet */ 01555 l = 0; /* Don't loop again */ 01556 goto endswitch; 01557 } 01558 GETCHAR(citype, p); /* Parse CI type */ 01559 GETCHAR(cilen, p); /* Parse CI length */ 01560 l -= cilen; /* Adjust remaining length */ 01561 next += cilen; /* Step to next CI */ 01562 01563 switch (citype) { /* Check CI type */ 01564 case CI_ADDRS: 01565 if (!ao->old_addrs || ho->neg_addr || 01566 cilen != CILEN_ADDRS) { /* Check CI length */ 01567 orc = CONFREJ; /* Reject CI */ 01568 break; 01569 } 01570 01571 /* 01572 * If he has no address, or if we both have his address but 01573 * disagree about it, then NAK it with our idea. 01574 * In particular, if we don't know his address, but he does, 01575 * then accept it. 01576 */ 01577 GETLONG(tl, p); /* Parse source address (his) */ 01578 ciaddr1 = htonl(tl); 01579 if (ciaddr1 != wo->hisaddr 01580 && (ciaddr1 == 0 || !wo->accept_remote)) { 01581 orc = CONFNAK; 01582 if (!reject_if_disagree) { 01583 DECPTR(sizeof(u32_t), p); 01584 tl = ntohl(wo->hisaddr); 01585 PUTLONG(tl, p); 01586 } 01587 } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 01588 /* 01589 * If neither we nor he knows his address, reject the option. 01590 */ 01591 orc = CONFREJ; 01592 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 01593 break; 01594 } 01595 01596 /* 01597 * If he doesn't know our address, or if we both have our address 01598 * but disagree about it, then NAK it with our idea. 01599 */ 01600 GETLONG(tl, p); /* Parse desination address (ours) */ 01601 ciaddr2 = htonl(tl); 01602 if (ciaddr2 != wo->ouraddr) { 01603 if (ciaddr2 == 0 || !wo->accept_local) { 01604 orc = CONFNAK; 01605 if (!reject_if_disagree) { 01606 DECPTR(sizeof(u32_t), p); 01607 tl = ntohl(wo->ouraddr); 01608 PUTLONG(tl, p); 01609 } 01610 } else { 01611 wo->ouraddr = ciaddr2; /* accept peer's idea */ 01612 } 01613 } 01614 01615 ho->old_addrs = 1; 01616 ho->hisaddr = ciaddr1; 01617 ho->ouraddr = ciaddr2; 01618 break; 01619 01620 case CI_ADDR: 01621 if (!ao->neg_addr || ho->old_addrs || 01622 cilen != CILEN_ADDR) { /* Check CI length */ 01623 orc = CONFREJ; /* Reject CI */ 01624 break; 01625 } 01626 01627 /* 01628 * If he has no address, or if we both have his address but 01629 * disagree about it, then NAK it with our idea. 01630 * In particular, if we don't know his address, but he does, 01631 * then accept it. 01632 */ 01633 GETLONG(tl, p); /* Parse source address (his) */ 01634 ciaddr1 = htonl(tl); 01635 if (ciaddr1 != wo->hisaddr 01636 && (ciaddr1 == 0 || !wo->accept_remote)) { 01637 orc = CONFNAK; 01638 if (!reject_if_disagree) { 01639 DECPTR(sizeof(u32_t), p); 01640 tl = ntohl(wo->hisaddr); 01641 PUTLONG(tl, p); 01642 } 01643 } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 01644 /* 01645 * Don't ACK an address of 0.0.0.0 - reject it instead. 01646 */ 01647 orc = CONFREJ; 01648 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 01649 break; 01650 } 01651 01652 ho->neg_addr = 1; 01653 ho->hisaddr = ciaddr1; 01654 break; 01655 01656 #if LWIP_DNS 01657 case CI_MS_DNS1: 01658 case CI_MS_DNS2: 01659 /* Microsoft primary or secondary DNS request */ 01660 d = citype == CI_MS_DNS2; 01661 01662 /* If we do not have a DNS address then we cannot send it */ 01663 if (ao->dnsaddr[d] == 0 || 01664 cilen != CILEN_ADDR) { /* Check CI length */ 01665 orc = CONFREJ; /* Reject CI */ 01666 break; 01667 } 01668 GETLONG(tl, p); 01669 if (htonl(tl) != ao->dnsaddr[d]) { 01670 DECPTR(sizeof(u32_t), p); 01671 tl = ntohl(ao->dnsaddr[d]); 01672 PUTLONG(tl, p); 01673 orc = CONFNAK; 01674 } 01675 break; 01676 #endif /* LWIP_DNS */ 01677 01678 #if 0 /* UNUSED - WINS */ 01679 case CI_MS_WINS1: 01680 case CI_MS_WINS2: 01681 /* Microsoft primary or secondary WINS request */ 01682 d = citype == CI_MS_WINS2; 01683 01684 /* If we do not have a DNS address then we cannot send it */ 01685 if (ao->winsaddr[d] == 0 || 01686 cilen != CILEN_ADDR) { /* Check CI length */ 01687 orc = CONFREJ; /* Reject CI */ 01688 break; 01689 } 01690 GETLONG(tl, p); 01691 if (htonl(tl) != ao->winsaddr[d]) { 01692 DECPTR(sizeof(u32_t), p); 01693 tl = ntohl(ao->winsaddr[d]); 01694 PUTLONG(tl, p); 01695 orc = CONFNAK; 01696 } 01697 break; 01698 #endif /* UNUSED - WINS */ 01699 01700 #if VJ_SUPPORT 01701 case CI_COMPRESSTYPE: 01702 if (!ao->neg_vj || 01703 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { 01704 orc = CONFREJ; 01705 break; 01706 } 01707 GETSHORT(cishort, p); 01708 01709 if (!(cishort == IPCP_VJ_COMP || 01710 (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { 01711 orc = CONFREJ; 01712 break; 01713 } 01714 01715 ho->neg_vj = 1; 01716 ho->vj_protocol = cishort; 01717 if (cilen == CILEN_VJ) { 01718 GETCHAR(maxslotindex, p); 01719 if (maxslotindex > ao->maxslotindex) { 01720 orc = CONFNAK; 01721 if (!reject_if_disagree){ 01722 DECPTR(1, p); 01723 PUTCHAR(ao->maxslotindex, p); 01724 } 01725 } 01726 GETCHAR(cflag, p); 01727 if (cflag && !ao->cflag) { 01728 orc = CONFNAK; 01729 if (!reject_if_disagree){ 01730 DECPTR(1, p); 01731 PUTCHAR(wo->cflag, p); 01732 } 01733 } 01734 ho->maxslotindex = maxslotindex; 01735 ho->cflag = cflag; 01736 } else { 01737 ho->old_vj = 1; 01738 ho->maxslotindex = MAX_STATES - 1; 01739 ho->cflag = 1; 01740 } 01741 break; 01742 #endif /* VJ_SUPPORT */ 01743 01744 default: 01745 orc = CONFREJ; 01746 break; 01747 } 01748 endswitch: 01749 if (orc == CONFACK && /* Good CI */ 01750 rc != CONFACK) /* but prior CI wasnt? */ 01751 continue; /* Don't send this one */ 01752 01753 if (orc == CONFNAK) { /* Nak this CI? */ 01754 if (reject_if_disagree) /* Getting fed up with sending NAKs? */ 01755 orc = CONFREJ; /* Get tough if so */ 01756 else { 01757 if (rc == CONFREJ) /* Rejecting prior CI? */ 01758 continue; /* Don't send this one */ 01759 if (rc == CONFACK) { /* Ack'd all prior CIs? */ 01760 rc = CONFNAK; /* Not anymore... */ 01761 ucp = inp; /* Backup */ 01762 } 01763 } 01764 } 01765 01766 if (orc == CONFREJ && /* Reject this CI */ 01767 rc != CONFREJ) { /* but no prior ones? */ 01768 rc = CONFREJ; 01769 ucp = inp; /* Backup */ 01770 } 01771 01772 /* Need to move CI? */ 01773 if (ucp != cip) 01774 MEMCPY(ucp, cip, cilen); /* Move it */ 01775 01776 /* Update output pointer */ 01777 INCPTR(cilen, ucp); 01778 } 01779 01780 /* 01781 * If we aren't rejecting this packet, and we want to negotiate 01782 * their address, and they didn't send their address, then we 01783 * send a NAK with a CI_ADDR option appended. We assume the 01784 * input buffer is long enough that we can append the extra 01785 * option safely. 01786 */ 01787 if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && 01788 wo->req_addr && !reject_if_disagree && !pcb->settings.noremoteip) { 01789 if (rc == CONFACK) { 01790 rc = CONFNAK; 01791 ucp = inp; /* reset pointer */ 01792 wo->req_addr = 0; /* don't ask again */ 01793 } 01794 PUTCHAR(CI_ADDR, ucp); 01795 PUTCHAR(CILEN_ADDR, ucp); 01796 tl = ntohl(wo->hisaddr); 01797 PUTLONG(tl, ucp); 01798 } 01799 01800 *len = ucp - inp; /* Compute output length */ 01801 IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); 01802 return (rc); /* Return final code */ 01803 } 01804 01805 01806 #if 0 /* UNUSED */ 01807 /* 01808 * ip_check_options - check that any IP-related options are OK, 01809 * and assign appropriate defaults. 01810 */ 01811 static void 01812 ip_check_options() 01813 { 01814 struct hostent *hp; 01815 u32_t local; 01816 ipcp_options *wo = &ipcp_wantoptions[0]; 01817 01818 /* 01819 * Default our local IP address based on our hostname. 01820 * If local IP address already given, don't bother. 01821 */ 01822 if (wo->ouraddr == 0 && !disable_defaultip) { 01823 /* 01824 * Look up our hostname (possibly with domain name appended) 01825 * and take the first IP address as our local IP address. 01826 * If there isn't an IP address for our hostname, too bad. 01827 */ 01828 wo->accept_local = 1; /* don't insist on this default value */ 01829 if ((hp = gethostbyname(hostname)) != NULL) { 01830 local = *(u32_t *)hp->h_addr; 01831 if (local != 0 && !bad_ip_adrs(local)) 01832 wo->ouraddr = local; 01833 } 01834 } 01835 ask_for_local = wo->ouraddr != 0 || !disable_defaultip; 01836 } 01837 #endif /* UNUSED */ 01838 01839 #if DEMAND_SUPPORT 01840 /* 01841 * ip_demand_conf - configure the interface as though 01842 * IPCP were up, for use with dial-on-demand. 01843 */ 01844 static int 01845 ip_demand_conf(u) 01846 int u; 01847 { 01848 ppp_pcb *pcb = &ppp_pcb_list[u]; 01849 ipcp_options *wo = &ipcp_wantoptions[u]; 01850 01851 if (wo->hisaddr == 0 && !pcb->settings.noremoteip) { 01852 /* make up an arbitrary address for the peer */ 01853 wo->hisaddr = htonl(0x0a707070 + ifunit); 01854 wo->accept_remote = 1; 01855 } 01856 if (wo->ouraddr == 0) { 01857 /* make up an arbitrary address for us */ 01858 wo->ouraddr = htonl(0x0a404040 + ifunit); 01859 wo->accept_local = 1; 01860 ask_for_local = 0; /* don't tell the peer this address */ 01861 } 01862 if (!sifaddr(pcb, wo->ouraddr, wo->hisaddr, get_mask(wo->ouraddr))) 01863 return 0; 01864 if (!sifup(pcb)) 01865 return 0; 01866 if (!sifnpmode(pcb, PPP_IP, NPMODE_QUEUE)) 01867 return 0; 01868 #if 0 /* UNUSED */ 01869 if (wo->default_route) 01870 if (sifdefaultroute(pcb, wo->ouraddr, wo->hisaddr, 01871 wo->replace_default_route)) 01872 default_route_set[u] = 1; 01873 #endif /* UNUSED */ 01874 #if 0 /* UNUSED - PROXY ARP */ 01875 if (wo->proxy_arp) 01876 if (sifproxyarp(pcb, wo->hisaddr)) 01877 proxy_arp_set[u] = 1; 01878 #endif /* UNUSED - PROXY ARP */ 01879 01880 ppp_notice("local IP address %I", wo->ouraddr); 01881 if (wo->hisaddr) 01882 ppp_notice("remote IP address %I", wo->hisaddr); 01883 01884 return 1; 01885 } 01886 #endif /* DEMAND_SUPPORT */ 01887 01888 /* 01889 * ipcp_up - IPCP has come UP. 01890 * 01891 * Configure the IP network interface appropriately and bring it up. 01892 */ 01893 static void ipcp_up(fsm *f) { 01894 ppp_pcb *pcb = f->pcb; 01895 u32_t mask; 01896 ipcp_options *ho = &pcb->ipcp_hisoptions; 01897 ipcp_options *go = &pcb->ipcp_gotoptions; 01898 ipcp_options *wo = &pcb->ipcp_wantoptions; 01899 01900 IPCPDEBUG(("ipcp: up")); 01901 01902 /* 01903 * We must have a non-zero IP address for both ends of the link. 01904 */ 01905 if (!ho->neg_addr && !ho->old_addrs) 01906 ho->hisaddr = wo->hisaddr; 01907 01908 if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) 01909 && wo->ouraddr != 0) { 01910 ppp_error("Peer refused to agree to our IP address"); 01911 ipcp_close(f->pcb, "Refused our IP address"); 01912 return; 01913 } 01914 if (go->ouraddr == 0) { 01915 ppp_error("Could not determine local IP address"); 01916 ipcp_close(f->pcb, "Could not determine local IP address"); 01917 return; 01918 } 01919 if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { 01920 ho->hisaddr = htonl(0x0a404040); 01921 ppp_warn("Could not determine remote IP address: defaulting to %I", 01922 ho->hisaddr); 01923 } 01924 #if 0 /* UNUSED */ 01925 script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); 01926 if (ho->hisaddr != 0) 01927 script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); 01928 #endif /* UNUSED */ 01929 01930 #if LWIP_DNS 01931 if (!go->req_dns1) 01932 go->dnsaddr[0] = 0; 01933 if (!go->req_dns2) 01934 go->dnsaddr[1] = 0; 01935 #if 0 /* UNUSED */ 01936 if (go->dnsaddr[0]) 01937 script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); 01938 if (go->dnsaddr[1]) 01939 script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); 01940 #endif /* UNUSED */ 01941 if (pcb->settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { 01942 sdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); 01943 #if 0 /* UNUSED */ 01944 script_setenv("USEPEERDNS", "1", 0); 01945 create_resolv(go->dnsaddr[0], go->dnsaddr[1]); 01946 #endif /* UNUSED */ 01947 } 01948 #endif /* LWIP_DNS */ 01949 01950 /* FIXME: check why it fails, just to know */ 01951 #if 0 /* Unused */ 01952 /* 01953 * Check that the peer is allowed to use the IP address it wants. 01954 */ 01955 if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { 01956 ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); 01957 ipcp_close(f->unit, "Unauthorized remote IP address"); 01958 return; 01959 } 01960 #endif /* Unused */ 01961 01962 #if VJ_SUPPORT 01963 /* set tcp compression */ 01964 sifvjcomp(pcb, ho->neg_vj, ho->cflag, ho->maxslotindex); 01965 #endif /* VJ_SUPPORT */ 01966 01967 #if DEMAND_SUPPORT 01968 /* 01969 * If we are doing dial-on-demand, the interface is already 01970 * configured, so we put out any saved-up packets, then set the 01971 * interface to pass IP packets. 01972 */ 01973 if (demand) { 01974 if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { 01975 ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, 01976 wo->replace_default_route); 01977 if (go->ouraddr != wo->ouraddr) { 01978 ppp_warn("Local IP address changed to %I", go->ouraddr); 01979 script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); 01980 wo->ouraddr = go->ouraddr; 01981 } else 01982 script_unsetenv("OLDIPLOCAL"); 01983 if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { 01984 ppp_warn("Remote IP address changed to %I", ho->hisaddr); 01985 script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); 01986 wo->hisaddr = ho->hisaddr; 01987 } else 01988 script_unsetenv("OLDIPREMOTE"); 01989 01990 /* Set the interface to the new addresses */ 01991 mask = get_mask(go->ouraddr); 01992 if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { 01993 #if PPP_DEBUG 01994 ppp_warn("Interface configuration failed"); 01995 #endif /* PPP_DEBUG */ 01996 ipcp_close(f->unit, "Interface configuration failed"); 01997 return; 01998 } 01999 02000 /* assign a default route through the interface if required */ 02001 if (ipcp_wantoptions[f->unit].default_route) 02002 if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, 02003 wo->replace_default_route)) 02004 default_route_set[f->unit] = 1; 02005 02006 #if 0 /* UNUSED - PROXY ARP */ 02007 /* Make a proxy ARP entry if requested. */ 02008 if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) 02009 if (sifproxyarp(pcb, ho->hisaddr)) 02010 proxy_arp_set[f->unit] = 1; 02011 #endif /* UNUSED - PROXY ARP */ 02012 02013 } 02014 demand_rexmit(PPP_IP,go->ouraddr); 02015 sifnpmode(pcb, PPP_IP, NPMODE_PASS); 02016 02017 } else 02018 #endif /* DEMAND_SUPPORT */ 02019 { 02020 /* 02021 * Set IP addresses and (if specified) netmask. 02022 */ 02023 mask = get_mask(go->ouraddr); 02024 02025 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) 02026 if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { 02027 #if PPP_DEBUG 02028 ppp_warn("Interface configuration failed"); 02029 #endif /* PPP_DEBUG */ 02030 ipcp_close(f->pcb, "Interface configuration failed"); 02031 return; 02032 } 02033 #endif 02034 02035 /* bring the interface up for IP */ 02036 if (!sifup(pcb)) { 02037 #if PPP_DEBUG 02038 ppp_warn("Interface failed to come up"); 02039 #endif /* PPP_DEBUG */ 02040 ipcp_close(f->pcb, "Interface configuration failed"); 02041 return; 02042 } 02043 02044 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) 02045 if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { 02046 #if PPP_DEBUG 02047 ppp_warn("Interface configuration failed"); 02048 #endif /* PPP_DEBUG */ 02049 ipcp_close(f->unit, "Interface configuration failed"); 02050 return; 02051 } 02052 #endif 02053 #if DEMAND_SUPPORT 02054 sifnpmode(pcb, PPP_IP, NPMODE_PASS); 02055 #endif /* DEMAND_SUPPORT */ 02056 02057 #if 0 /* UNUSED */ 02058 /* assign a default route through the interface if required */ 02059 if (wo->default_route) 02060 if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, 02061 wo->replace_default_route)) 02062 pcb->default_route_set = 1; 02063 #endif /* UNUSED */ 02064 02065 #if 0 /* UNUSED - PROXY ARP */ 02066 /* Make a proxy ARP entry if requested. */ 02067 if (ho->hisaddr != 0 && wo->proxy_arp) 02068 if (sifproxyarp(pcb, ho->hisaddr)) 02069 pcb->proxy_arp_set = 1; 02070 #endif /* UNUSED - PROXY ARP */ 02071 02072 wo->ouraddr = go->ouraddr; 02073 02074 ppp_notice("local IP address %I", go->ouraddr); 02075 if (ho->hisaddr != 0) 02076 ppp_notice("remote IP address %I", ho->hisaddr); 02077 #if LWIP_DNS 02078 if (go->dnsaddr[0]) 02079 ppp_notice("primary DNS address %I", go->dnsaddr[0]); 02080 if (go->dnsaddr[1]) 02081 ppp_notice("secondary DNS address %I", go->dnsaddr[1]); 02082 #endif /* LWIP_DNS */ 02083 } 02084 02085 #if PPP_STATS_SUPPORT 02086 reset_link_stats(f->unit); 02087 #endif /* PPP_STATS_SUPPORT */ 02088 02089 np_up(pcb, PPP_IP); 02090 pcb->ipcp_is_up = 1; 02091 02092 #if PPP_NOTIFY 02093 notify(ip_up_notifier, 0); 02094 #endif /* PPP_NOTIFY */ 02095 #if 0 /* UNUSED */ 02096 if (ip_up_hook) 02097 ip_up_hook(); 02098 #endif /* UNUSED */ 02099 } 02100 02101 02102 /* 02103 * ipcp_down - IPCP has gone DOWN. 02104 * 02105 * Take the IP network interface down, clear its addresses 02106 * and delete routes through it. 02107 */ 02108 static void ipcp_down(fsm *f) { 02109 ppp_pcb *pcb = f->pcb; 02110 ipcp_options *ho = &pcb->ipcp_hisoptions; 02111 ipcp_options *go = &pcb->ipcp_gotoptions; 02112 02113 IPCPDEBUG(("ipcp: down")); 02114 #if PPP_STATS_SUPPORT 02115 /* XXX a bit IPv4-centric here, we only need to get the stats 02116 * before the interface is marked down. */ 02117 /* XXX more correct: we must get the stats before running the notifiers, 02118 * at least for the radius plugin */ 02119 update_link_stats(f->unit); 02120 #endif /* PPP_STATS_SUPPORT */ 02121 #if PPP_NOTIFY 02122 notify(ip_down_notifier, 0); 02123 #endif /* PPP_NOTIFY */ 02124 #if 0 /* UNUSED */ 02125 if (ip_down_hook) 02126 ip_down_hook(); 02127 #endif /* UNUSED */ 02128 if (pcb->ipcp_is_up) { 02129 pcb->ipcp_is_up = 0; 02130 np_down(pcb, PPP_IP); 02131 } 02132 #if VJ_SUPPORT 02133 sifvjcomp(pcb, 0, 0, 0); 02134 #endif /* VJ_SUPPORT */ 02135 02136 #if PPP_STATS_SUPPORT 02137 print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), 02138 * because print_link_stats() sets link_stats_valid 02139 * to 0 (zero) */ 02140 #endif /* PPP_STATS_SUPPORT */ 02141 02142 #if DEMAND_SUPPORT 02143 /* 02144 * If we are doing dial-on-demand, set the interface 02145 * to queue up outgoing packets (for now). 02146 */ 02147 if (demand) { 02148 sifnpmode(pcb, PPP_IP, NPMODE_QUEUE); 02149 } else 02150 #endif /* DEMAND_SUPPORT */ 02151 { 02152 #if DEMAND_SUPPORT 02153 sifnpmode(pcb, PPP_IP, NPMODE_DROP); 02154 #endif /* DEMAND_SUPPORT */ 02155 sifdown(pcb); 02156 ipcp_clear_addrs(pcb, go->ouraddr, 02157 ho->hisaddr, 0); 02158 #if LWIP_DNS 02159 cdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); 02160 #endif /* LWIP_DNS */ 02161 } 02162 } 02163 02164 02165 /* 02166 * ipcp_clear_addrs() - clear the interface addresses, routes, 02167 * proxy arp entries, etc. 02168 */ 02169 static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute) { 02170 LWIP_UNUSED_ARG(replacedefaultroute); 02171 02172 #if 0 /* UNUSED - PROXY ARP */ 02173 if (pcb->proxy_arp_set) { 02174 cifproxyarp(pcb, hisaddr); 02175 pcb->proxy_arp_set = 0; 02176 } 02177 #endif /* UNUSED - PROXY ARP */ 02178 #if 0 /* UNUSED */ 02179 /* If replacedefaultroute, sifdefaultroute will be called soon 02180 * with replacedefaultroute set and that will overwrite the current 02181 * default route. This is the case only when doing demand, otherwise 02182 * during demand, this cifdefaultroute would restore the old default 02183 * route which is not what we want in this case. In the non-demand 02184 * case, we'll delete the default route and restore the old if there 02185 * is one saved by an sifdefaultroute with replacedefaultroute. 02186 */ 02187 if (!replacedefaultroute && pcb->default_route_set) { 02188 cifdefaultroute(pcb, ouraddr, hisaddr); 02189 pcb->default_route_set = 0; 02190 } 02191 #endif /* UNUSED */ 02192 cifaddr(pcb, ouraddr, hisaddr); 02193 } 02194 02195 02196 /* 02197 * ipcp_finished - possibly shut down the lower layers. 02198 */ 02199 static void ipcp_finished(fsm *f) { 02200 ppp_pcb *pcb = f->pcb; 02201 if (pcb->ipcp_is_open) { 02202 pcb->ipcp_is_open = 0; 02203 np_finished(pcb, PPP_IP); 02204 } 02205 } 02206 02207 02208 #if 0 /* UNUSED */ 02209 /* 02210 * create_resolv - create the replacement resolv.conf file 02211 */ 02212 static void 02213 create_resolv(peerdns1, peerdns2) 02214 u32_t peerdns1, peerdns2; 02215 { 02216 02217 } 02218 #endif /* UNUSED */ 02219 02220 #if PRINTPKT_SUPPORT 02221 /* 02222 * ipcp_printpkt - print the contents of an IPCP packet. 02223 */ 02224 static const char* const ipcp_codenames[] = { 02225 "ConfReq", "ConfAck", "ConfNak", "ConfRej", 02226 "TermReq", "TermAck", "CodeRej" 02227 }; 02228 02229 static int ipcp_printpkt(const u_char *p, int plen, 02230 void (*printer) (void *, const char *, ...), void *arg) { 02231 int code, id, len, olen; 02232 const u_char *pstart, *optend; 02233 #if VJ_SUPPORT 02234 u_short cishort; 02235 #endif /* VJ_SUPPORT */ 02236 u32_t cilong; 02237 02238 if (plen < HEADERLEN) 02239 return 0; 02240 pstart = p; 02241 GETCHAR(code, p); 02242 GETCHAR(id, p); 02243 GETSHORT(len, p); 02244 if (len < HEADERLEN || len > plen) 02245 return 0; 02246 02247 if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipcp_codenames)) 02248 printer(arg, " %s", ipcp_codenames[code-1]); 02249 else 02250 printer(arg, " code=0x%x", code); 02251 printer(arg, " id=0x%x", id); 02252 len -= HEADERLEN; 02253 switch (code) { 02254 case CONFREQ: 02255 case CONFACK: 02256 case CONFNAK: 02257 case CONFREJ: 02258 /* print option list */ 02259 while (len >= 2) { 02260 GETCHAR(code, p); 02261 GETCHAR(olen, p); 02262 p -= 2; 02263 if (olen < 2 || olen > len) { 02264 break; 02265 } 02266 printer(arg, " <"); 02267 len -= olen; 02268 optend = p + olen; 02269 switch (code) { 02270 case CI_ADDRS: 02271 if (olen == CILEN_ADDRS) { 02272 p += 2; 02273 GETLONG(cilong, p); 02274 printer(arg, "addrs %I", htonl(cilong)); 02275 GETLONG(cilong, p); 02276 printer(arg, " %I", htonl(cilong)); 02277 } 02278 break; 02279 #if VJ_SUPPORT 02280 case CI_COMPRESSTYPE: 02281 if (olen >= CILEN_COMPRESS) { 02282 p += 2; 02283 GETSHORT(cishort, p); 02284 printer(arg, "compress "); 02285 switch (cishort) { 02286 case IPCP_VJ_COMP: 02287 printer(arg, "VJ"); 02288 break; 02289 case IPCP_VJ_COMP_OLD: 02290 printer(arg, "old-VJ"); 02291 break; 02292 default: 02293 printer(arg, "0x%x", cishort); 02294 } 02295 } 02296 break; 02297 #endif /* VJ_SUPPORT */ 02298 case CI_ADDR: 02299 if (olen == CILEN_ADDR) { 02300 p += 2; 02301 GETLONG(cilong, p); 02302 printer(arg, "addr %I", htonl(cilong)); 02303 } 02304 break; 02305 #if LWIP_DNS 02306 case CI_MS_DNS1: 02307 case CI_MS_DNS2: 02308 p += 2; 02309 GETLONG(cilong, p); 02310 printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2), 02311 htonl(cilong)); 02312 break; 02313 #endif /* LWIP_DNS */ 02314 #if 0 /* UNUSED - WINS */ 02315 case CI_MS_WINS1: 02316 case CI_MS_WINS2: 02317 p += 2; 02318 GETLONG(cilong, p); 02319 printer(arg, "ms-wins %I", htonl(cilong)); 02320 break; 02321 #endif /* UNUSED - WINS */ 02322 default: 02323 break; 02324 } 02325 while (p < optend) { 02326 GETCHAR(code, p); 02327 printer(arg, " %.2x", code); 02328 } 02329 printer(arg, ">"); 02330 } 02331 break; 02332 02333 case TERMACK: 02334 case TERMREQ: 02335 if (len > 0 && *p >= ' ' && *p < 0x7f) { 02336 printer(arg, " "); 02337 ppp_print_string(p, len, printer, arg); 02338 p += len; 02339 len = 0; 02340 } 02341 break; 02342 default: 02343 break; 02344 } 02345 02346 /* print the rest of the bytes in the packet */ 02347 for (; len > 0; --len) { 02348 GETCHAR(code, p); 02349 printer(arg, " %.2x", code); 02350 } 02351 02352 return p - pstart; 02353 } 02354 #endif /* PRINTPKT_SUPPORT */ 02355 02356 #if DEMAND_SUPPORT 02357 /* 02358 * ip_active_pkt - see if this IP packet is worth bringing the link up for. 02359 * We don't bring the link up for IP fragments or for TCP FIN packets 02360 * with no data. 02361 */ 02362 #define IP_HDRLEN 20 /* bytes */ 02363 #define IP_OFFMASK 0x1fff 02364 #ifndef IPPROTO_TCP 02365 #define IPPROTO_TCP 6 02366 #endif 02367 #define TCP_HDRLEN 20 02368 #define TH_FIN 0x01 02369 02370 /* 02371 * We use these macros because the IP header may be at an odd address, 02372 * and some compilers might use word loads to get th_off or ip_hl. 02373 */ 02374 02375 #define net_short(x) (((x)[0] << 8) + (x)[1]) 02376 #define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) 02377 #define get_ipoff(x) net_short((unsigned char *)(x) + 6) 02378 #define get_ipproto(x) (((unsigned char *)(x))[9]) 02379 #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) 02380 #define get_tcpflags(x) (((unsigned char *)(x))[13]) 02381 02382 static int 02383 ip_active_pkt(pkt, len) 02384 u_char *pkt; 02385 int len; 02386 { 02387 u_char *tcp; 02388 int hlen; 02389 02390 len -= PPP_HDRLEN; 02391 pkt += PPP_HDRLEN; 02392 if (len < IP_HDRLEN) 02393 return 0; 02394 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) 02395 return 0; 02396 if (get_ipproto(pkt) != IPPROTO_TCP) 02397 return 1; 02398 hlen = get_iphl(pkt) * 4; 02399 if (len < hlen + TCP_HDRLEN) 02400 return 0; 02401 tcp = pkt + hlen; 02402 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) 02403 return 0; 02404 return 1; 02405 } 02406 #endif /* DEMAND_SUPPORT */ 02407 02408 #endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */
Generated on Tue Jul 12 2022 11:02:41 by
