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