Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
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 13:15:53 by
1.7.2
