Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
lwip_nd6.c
Go to the documentation of this file.
00001 /** 00002 * @file 00003 * 00004 * Neighbor discovery and stateless address autoconfiguration for IPv6. 00005 * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 00006 * (Address autoconfiguration). 00007 */ 00008 00009 /* 00010 * Copyright (c) 2010 Inico Technologies Ltd. 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 2. Redistributions in binary form must reproduce the above copyright notice, 00019 * this list of conditions and the following disclaimer in the documentation 00020 * and/or other materials provided with the distribution. 00021 * 3. The name of the author may not be used to endorse or promote products 00022 * derived from this software without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00025 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00026 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00027 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00028 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00029 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00030 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00031 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00032 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00033 * OF SUCH DAMAGE. 00034 * 00035 * This file is part of the lwIP TCP/IP stack. 00036 * 00037 * Author: Ivan Delamer <delamer@inicotech.com> 00038 * 00039 * 00040 * Please coordinate changes and requests with Ivan Delamer 00041 * <delamer@inicotech.com> 00042 */ 00043 00044 #include "lwip/opt.h" 00045 00046 #if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ 00047 00048 #include "lwip/nd6.h" 00049 #include "lwip/priv/nd6_priv.h" 00050 #include "lwip/prot/nd6.h" 00051 #include "lwip/prot/icmp6.h" 00052 #include "lwip/pbuf.h" 00053 #include "lwip/mem.h" 00054 #include "lwip/memp.h" 00055 #include "lwip/ip6.h" 00056 #include "lwip/ip6_addr.h" 00057 #include "lwip/inet_chksum.h" 00058 #include "lwip/netif.h" 00059 #include "lwip/icmp6.h" 00060 #include "lwip/mld6.h" 00061 #include "lwip/ip.h" 00062 #include "lwip/stats.h" 00063 #include "lwip/dns.h" 00064 00065 #include <string.h> 00066 00067 #ifdef LWIP_HOOK_FILENAME 00068 #include LWIP_HOOK_FILENAME 00069 #endif 00070 00071 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK 00072 #error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK 00073 #endif 00074 00075 /* Router tables. */ 00076 struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; 00077 struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; 00078 struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; 00079 struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; 00080 00081 /* Default values, can be updated by a RA message. */ 00082 u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; 00083 u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */ 00084 00085 /* Index for cache entries. */ 00086 static u8_t nd6_cached_neighbor_index; 00087 static u8_t nd6_cached_destination_index; 00088 00089 /* Multicast address holder. */ 00090 static ip6_addr_t multicast_address; 00091 00092 /* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ 00093 static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; 00094 00095 /* Forward declarations. */ 00096 static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr); 00097 static s8_t nd6_new_neighbor_cache_entry(void); 00098 static void nd6_free_neighbor_cache_entry(s8_t i); 00099 static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); 00100 static s8_t nd6_new_destination_cache_entry(void); 00101 static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); 00102 static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); 00103 static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); 00104 static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); 00105 static s8_t nd6_get_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif); 00106 static s8_t nd6_new_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif); 00107 static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif); 00108 static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q); 00109 00110 #define ND6_SEND_FLAG_MULTICAST_DEST 0x01 00111 #define ND6_SEND_FLAG_ALLNODES_DEST 0x02 00112 #define ND6_SEND_FLAG_ANY_SRC 0x04 00113 static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); 00114 static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); 00115 static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags); 00116 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 00117 static err_t nd6_send_rs(struct netif *netif); 00118 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 00119 00120 #if LWIP_ND6_QUEUEING 00121 static void nd6_free_q(struct nd6_q_entry *q); 00122 #else /* LWIP_ND6_QUEUEING */ 00123 #define nd6_free_q(q) pbuf_free(q) 00124 #endif /* LWIP_ND6_QUEUEING */ 00125 static void nd6_send_q(s8_t i); 00126 00127 00128 /** 00129 * A local address has been determined to be a duplicate. Take the appropriate 00130 * action(s) on the address and the interface as a whole. 00131 * 00132 * @param netif the netif that owns the address 00133 * @param addr_idx the index of the address detected to be a duplicate 00134 */ 00135 static void 00136 nd6_duplicate_addr_detected(struct netif *netif, s8_t addr_idx) 00137 { 00138 00139 /* Mark the address as duplicate, but leave its lifetimes alone. If this was 00140 * a manually assigned address, it will remain in existence as duplicate, and 00141 * as such be unusable for any practical purposes until manual intervention. 00142 * If this was an autogenerated address, the address will follow normal 00143 * expiration rules, and thus disappear once its valid lifetime expires. */ 00144 netif_ip6_addr_set_state(netif, addr_idx, IP6_ADDR_DUPLICATED); 00145 00146 #if LWIP_IPV6_AUTOCONFIG 00147 /* If the affected address was the link-local address that we use to generate 00148 * all other addresses, then we should not continue to use those derived 00149 * addresses either, so mark them as duplicate as well. For autoconfig-only 00150 * setups, this will make the interface effectively unusable, approaching the 00151 * intention of RFC 4862 Sec. 5.4.5. @todo implement the full requirements */ 00152 if (addr_idx == 0) { 00153 s8_t i; 00154 for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00155 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && 00156 !netif_ip6_addr_isstatic(netif, i)) { 00157 netif_ip6_addr_set_state(netif, i, IP6_ADDR_DUPLICATED); 00158 } 00159 } 00160 } 00161 #endif /* LWIP_IPV6_AUTOCONFIG */ 00162 } 00163 00164 #if LWIP_IPV6_AUTOCONFIG 00165 /** 00166 * We received a router advertisement that contains a prefix with the 00167 * autoconfiguration flag set. Add or update an associated autogenerated 00168 * address. 00169 * 00170 * @param netif the netif on which the router advertisement arrived 00171 * @param prefix_opt a pointer to the prefix option data 00172 * @param prefix_addr an aligned copy of the prefix address 00173 */ 00174 static void 00175 nd6_process_autoconfig_prefix(struct netif *netif, 00176 struct prefix_option *prefix_opt, const ip6_addr_t *prefix_addr) 00177 { 00178 ip6_addr_t ip6addr; 00179 u32_t valid_life, pref_life; 00180 u8_t addr_state; 00181 s8_t i, free_idx; 00182 00183 /* The caller already checks RFC 4862 Sec. 5.5.3 points (a) and (b). We do 00184 * the rest, starting with checks for (c) and (d) here. */ 00185 valid_life = lwip_htonl(prefix_opt->valid_lifetime); 00186 pref_life = lwip_htonl(prefix_opt->preferred_lifetime); 00187 if (pref_life > valid_life || prefix_opt->prefix_length != 64) { 00188 return; /* silently ignore this prefix for autoconfiguration purposes */ 00189 } 00190 00191 /* If an autogenerated address already exists for this prefix, update its 00192 * lifetimes. An address is considered autogenerated if 1) it is not static 00193 * (i.e., manually assigned), and 2) there is an advertised autoconfiguration 00194 * prefix for it (the one we are processing here). This does not necessarily 00195 * exclude the possibility that the address was actually assigned by, say, 00196 * DHCPv6. If that distinction becomes important in the future, more state 00197 * must be kept. As explained elsewhere we also update lifetimes of tentative 00198 * and duplicate addresses. Skip address slot 0 (the link-local address). */ 00199 for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00200 addr_state = netif_ip6_addr_state(netif, i); 00201 if (!ip6_addr_isinvalid(addr_state) && !netif_ip6_addr_isstatic(netif, i) && 00202 ip6_addr_netcmp(prefix_addr, netif_ip6_addr(netif, i))) { 00203 /* Update the valid lifetime, as per RFC 4862 Sec. 5.5.3 point (e). 00204 * The valid lifetime will never drop to zero as a result of this. */ 00205 u32_t remaining_life = netif_ip6_addr_valid_life(netif, i); 00206 if (valid_life > ND6_2HRS || valid_life > remaining_life) { 00207 netif_ip6_addr_set_valid_life(netif, i, valid_life); 00208 } else if (remaining_life > ND6_2HRS) { 00209 netif_ip6_addr_set_valid_life(netif, i, ND6_2HRS); 00210 } 00211 LWIP_ASSERT("bad valid lifetime", !netif_ip6_addr_isstatic(netif, i)); 00212 /* Update the preferred lifetime. No bounds checks are needed here. In 00213 * rare cases the advertisement may un-deprecate the address, though. 00214 * Deprecation is left to the timer code where it is handled anyway. */ 00215 if (pref_life > 0 && addr_state == IP6_ADDR_DEPRECATED) { 00216 netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED); 00217 } 00218 netif_ip6_addr_set_pref_life(netif, i, pref_life); 00219 return; /* there should be at most one matching address */ 00220 } 00221 } 00222 00223 /* No autogenerated address exists for this prefix yet. See if we can add a 00224 * new one. However, if IPv6 autoconfiguration is administratively disabled, 00225 * do not generate new addresses, but do keep updating lifetimes for existing 00226 * addresses. Also, when adding new addresses, we must protect explicitly 00227 * against a valid lifetime of zero, because again, we use that as a special 00228 * value. The generated address would otherwise expire immediately anyway. 00229 * Finally, the original link-local address must be usable at all. We start 00230 * creating addresses even if the link-local address is still in tentative 00231 * state though, and deal with the fallout of that upon DAD collision. */ 00232 addr_state = netif_ip6_addr_state(netif, 0); 00233 if (!netif->ip6_autoconfig_enabled || valid_life == IP6_ADDR_LIFE_STATIC || 00234 ip6_addr_isinvalid(addr_state) || ip6_addr_isduplicated(addr_state)) { 00235 return; 00236 } 00237 00238 /* Construct the new address that we intend to use, and then see if that 00239 * address really does not exist. It might have been added manually, after 00240 * all. As a side effect, find a free slot. Note that we cannot use 00241 * netif_add_ip6_address() here, as it would return ERR_OK if the address 00242 * already did exist, resulting in that address being given lifetimes. */ 00243 IP6_ADDR(&ip6addr, prefix_addr->addr[0], prefix_addr->addr[1], 00244 netif_ip6_addr(netif, 0)->addr[2], netif_ip6_addr(netif, 0)->addr[3]); 00245 00246 free_idx = 0; 00247 for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00248 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { 00249 if (ip6_addr_cmp(&ip6addr, netif_ip6_addr(netif, i))) { 00250 return; /* formed address already exists */ 00251 } 00252 } else if (free_idx == 0) { 00253 free_idx = i; 00254 } 00255 } 00256 if (free_idx == 0) { 00257 return; /* no address slots available, try again on next advertisement */ 00258 } 00259 00260 /* Assign the new address to the interface. */ 00261 ip_addr_copy_from_ip6(netif->ip6_addr[free_idx], ip6addr); 00262 netif_ip6_addr_set_valid_life(netif, free_idx, valid_life); 00263 netif_ip6_addr_set_pref_life(netif, free_idx, pref_life); 00264 netif_ip6_addr_set_state(netif, free_idx, IP6_ADDR_TENTATIVE); 00265 } 00266 #endif /* LWIP_IPV6_AUTOCONFIG */ 00267 00268 /** 00269 * Process an incoming neighbor discovery message 00270 * 00271 * @param p the nd packet, p->payload pointing to the icmpv6 header 00272 * @param inp the netif on which this packet was received 00273 */ 00274 void 00275 nd6_input(struct pbuf *p, struct netif *inp) 00276 { 00277 u8_t msg_type; 00278 s8_t i; 00279 00280 ND6_STATS_INC(nd6.recv); 00281 00282 msg_type = *((u8_t *)p->payload); 00283 switch (msg_type) { 00284 case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ 00285 { 00286 struct na_header *na_hdr; 00287 struct lladdr_option *lladdr_opt; 00288 ip6_addr_t target_address; 00289 00290 /* Check that na header fits in packet. */ 00291 if (p->len < (sizeof(struct na_header))) { 00292 /* @todo debug message */ 00293 pbuf_free(p); 00294 ND6_STATS_INC(nd6.lenerr); 00295 ND6_STATS_INC(nd6.drop); 00296 return; 00297 } 00298 00299 na_hdr = (struct na_header *)p->payload; 00300 00301 /* Create an aligned copy of the target address. */ 00302 ip6_addr_set(&target_address, &(na_hdr->target_address)); 00303 00304 /* Check a subset of the other RFC 4861 Sec. 7.1.2 requirements. */ 00305 if (IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || na_hdr->code != 0 || 00306 ip6_addr_ismulticast(&target_address)) { 00307 pbuf_free(p); 00308 ND6_STATS_INC(nd6.proterr); 00309 ND6_STATS_INC(nd6.drop); 00310 return; 00311 } 00312 00313 /* @todo RFC MUST: if IP destination is multicast, Solicited flag is zero */ 00314 /* @todo RFC MUST: all included options have a length greater than zero */ 00315 00316 /* Unsolicited NA?*/ 00317 if (ip6_addr_ismulticast(ip6_current_dest_addr())) { 00318 /* This is an unsolicited NA. 00319 * link-layer changed? 00320 * part of DAD mechanism? */ 00321 00322 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS 00323 /* If the target address matches this netif, it is a DAD response. */ 00324 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00325 if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && 00326 !ip6_addr_isduplicated(netif_ip6_addr_state(inp, i)) && 00327 ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { 00328 /* We are using a duplicate address. */ 00329 nd6_duplicate_addr_detected(inp, i); 00330 00331 pbuf_free(p); 00332 return; 00333 } 00334 } 00335 #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ 00336 00337 /* Check that link-layer address option also fits in packet. */ 00338 if (p->len < (sizeof(struct na_header) + 2)) { 00339 /* @todo debug message */ 00340 pbuf_free(p); 00341 ND6_STATS_INC(nd6.lenerr); 00342 ND6_STATS_INC(nd6.drop); 00343 return; 00344 } 00345 00346 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); 00347 00348 if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { 00349 /* @todo debug message */ 00350 pbuf_free(p); 00351 ND6_STATS_INC(nd6.lenerr); 00352 ND6_STATS_INC(nd6.drop); 00353 return; 00354 } 00355 00356 /* This is an unsolicited NA, most likely there was a LLADDR change. */ 00357 i = nd6_find_neighbor_cache_entry(&target_address); 00358 if (i >= 0) { 00359 if (na_hdr->flags & ND6_FLAG_OVERRIDE) { 00360 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 00361 } 00362 } 00363 } else { 00364 /* This is a solicited NA. 00365 * neighbor address resolution response? 00366 * neighbor unreachability detection response? */ 00367 00368 /* Find the cache entry corresponding to this na. */ 00369 i = nd6_find_neighbor_cache_entry(&target_address); 00370 if (i < 0) { 00371 /* We no longer care about this target address. drop it. */ 00372 pbuf_free(p); 00373 return; 00374 } 00375 00376 /* Update cache entry. */ 00377 if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || 00378 (neighbor_cache[i].state == ND6_INCOMPLETE)) { 00379 /* Check that link-layer address option also fits in packet. */ 00380 if (p->len < (sizeof(struct na_header) + 2)) { 00381 /* @todo debug message */ 00382 pbuf_free(p); 00383 ND6_STATS_INC(nd6.lenerr); 00384 ND6_STATS_INC(nd6.drop); 00385 return; 00386 } 00387 00388 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); 00389 00390 if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { 00391 /* @todo debug message */ 00392 pbuf_free(p); 00393 ND6_STATS_INC(nd6.lenerr); 00394 ND6_STATS_INC(nd6.drop); 00395 return; 00396 } 00397 00398 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 00399 } 00400 00401 neighbor_cache[i].netif = inp; 00402 neighbor_cache[i].state = ND6_REACHABLE; 00403 neighbor_cache[i].counter.reachable_time = reachable_time; 00404 00405 /* Send queued packets, if any. */ 00406 if (neighbor_cache[i].q != NULL) { 00407 nd6_send_q(i); 00408 } 00409 } 00410 00411 break; /* ICMP6_TYPE_NA */ 00412 } 00413 case ICMP6_TYPE_NS: /* Neighbor solicitation. */ 00414 { 00415 struct ns_header *ns_hdr; 00416 struct lladdr_option *lladdr_opt; 00417 ip6_addr_t target_address; 00418 u8_t accepted; 00419 00420 /* Check that ns header fits in packet. */ 00421 if (p->len < sizeof(struct ns_header)) { 00422 /* @todo debug message */ 00423 pbuf_free(p); 00424 ND6_STATS_INC(nd6.lenerr); 00425 ND6_STATS_INC(nd6.drop); 00426 return; 00427 } 00428 00429 ns_hdr = (struct ns_header *)p->payload; 00430 00431 /* Create an aligned copy of the target address. */ 00432 ip6_addr_set(&target_address, &(ns_hdr->target_address)); 00433 00434 /* Check a subset of the other RFC 4861 Sec. 7.1.1 requirements. */ 00435 if (IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || ns_hdr->code != 0 || 00436 ip6_addr_ismulticast(&target_address)) { 00437 pbuf_free(p); 00438 ND6_STATS_INC(nd6.proterr); 00439 ND6_STATS_INC(nd6.drop); 00440 return; 00441 } 00442 00443 /* @todo RFC MUST: all included options have a length greater than zero */ 00444 /* @todo RFC MUST: if IP source is 'any', destination is solicited-node multicast address */ 00445 /* @todo RFC MUST: if IP source is 'any', there is no source LL address option */ 00446 00447 /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ 00448 if (p->len >= (sizeof(struct ns_header) + 2)) { 00449 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); 00450 if (p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) { 00451 lladdr_opt = NULL; 00452 } 00453 } else { 00454 lladdr_opt = NULL; 00455 } 00456 00457 /* Check if the target address is configured on the receiving netif. */ 00458 accepted = 0; 00459 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { 00460 if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || 00461 (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && 00462 ip6_addr_isany(ip6_current_src_addr()))) && 00463 ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { 00464 accepted = 1; 00465 break; 00466 } 00467 } 00468 00469 /* NS not for us? */ 00470 if (!accepted) { 00471 pbuf_free(p); 00472 return; 00473 } 00474 00475 /* Check for ANY address in src (DAD algorithm). */ 00476 if (ip6_addr_isany(ip6_current_src_addr())) { 00477 /* Sender is validating this address. */ 00478 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { 00479 if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && 00480 ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { 00481 /* Send a NA back so that the sender does not use this address. */ 00482 nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); 00483 if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { 00484 /* We shouldn't use this address either. */ 00485 nd6_duplicate_addr_detected(inp, i); 00486 } 00487 } 00488 } 00489 } else { 00490 /* Sender is trying to resolve our address. */ 00491 /* Verify that they included their own link-layer address. */ 00492 if (lladdr_opt == NULL) { 00493 /* Not a valid message. */ 00494 pbuf_free(p); 00495 ND6_STATS_INC(nd6.proterr); 00496 ND6_STATS_INC(nd6.drop); 00497 return; 00498 } 00499 00500 i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); 00501 if (i>= 0) { 00502 /* We already have a record for the solicitor. */ 00503 if (neighbor_cache[i].state == ND6_INCOMPLETE) { 00504 neighbor_cache[i].netif = inp; 00505 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 00506 00507 /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ 00508 neighbor_cache[i].state = ND6_DELAY; 00509 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 00510 } 00511 } else { 00512 /* Add their IPv6 address and link-layer address to neighbor cache. 00513 * We will need it at least to send a unicast NA message, but most 00514 * likely we will also be communicating with this node soon. */ 00515 i = nd6_new_neighbor_cache_entry(); 00516 if (i < 0) { 00517 /* We couldn't assign a cache entry for this neighbor. 00518 * we won't be able to reply. drop it. */ 00519 pbuf_free(p); 00520 ND6_STATS_INC(nd6.memerr); 00521 return; 00522 } 00523 neighbor_cache[i].netif = inp; 00524 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 00525 ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); 00526 00527 /* Receiving a message does not prove reachability: only in one direction. 00528 * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ 00529 neighbor_cache[i].state = ND6_DELAY; 00530 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 00531 } 00532 00533 /* Send back a NA for us. Allocate the reply pbuf. */ 00534 nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); 00535 } 00536 00537 break; /* ICMP6_TYPE_NS */ 00538 } 00539 case ICMP6_TYPE_RA: /* Router Advertisement. */ 00540 { 00541 struct ra_header *ra_hdr; 00542 u8_t *buffer; /* Used to copy options. */ 00543 u16_t offset; 00544 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS 00545 /* There can by multiple RDNSS options per RA */ 00546 u8_t rdnss_server_idx = 0; 00547 #endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ 00548 00549 /* Check that RA header fits in packet. */ 00550 if (p->len < sizeof(struct ra_header)) { 00551 /* @todo debug message */ 00552 pbuf_free(p); 00553 ND6_STATS_INC(nd6.lenerr); 00554 ND6_STATS_INC(nd6.drop); 00555 return; 00556 } 00557 00558 ra_hdr = (struct ra_header *)p->payload; 00559 00560 /* Check a subset of the other RFC 4861 Sec. 6.1.2 requirements. */ 00561 if (!ip6_addr_islinklocal(ip6_current_src_addr()) || 00562 IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || ra_hdr->code != 0) { 00563 pbuf_free(p); 00564 ND6_STATS_INC(nd6.proterr); 00565 ND6_STATS_INC(nd6.drop); 00566 return; 00567 } 00568 00569 /* @todo RFC MUST: all included options have a length greater than zero */ 00570 00571 /* If we are sending RS messages, stop. */ 00572 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 00573 /* ensure at least one solicitation is sent */ 00574 if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) || 00575 (nd6_send_rs(inp) == ERR_OK)) { 00576 inp->rs_count = 0; 00577 } 00578 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 00579 00580 /* Get the matching default router entry. */ 00581 i = nd6_get_router(ip6_current_src_addr(), inp); 00582 if (i < 0) { 00583 /* Create a new router entry. */ 00584 i = nd6_new_router(ip6_current_src_addr(), inp); 00585 } 00586 00587 if (i < 0) { 00588 /* Could not create a new router entry. */ 00589 pbuf_free(p); 00590 ND6_STATS_INC(nd6.memerr); 00591 return; 00592 } 00593 00594 /* Re-set invalidation timer. */ 00595 default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime); 00596 00597 /* Re-set default timer values. */ 00598 #if LWIP_ND6_ALLOW_RA_UPDATES 00599 if (ra_hdr->retrans_timer > 0) { 00600 retrans_timer = lwip_htonl(ra_hdr->retrans_timer); 00601 } 00602 if (ra_hdr->reachable_time > 0) { 00603 reachable_time = lwip_htonl(ra_hdr->reachable_time); 00604 } 00605 #endif /* LWIP_ND6_ALLOW_RA_UPDATES */ 00606 00607 /* @todo set default hop limit... */ 00608 /* ra_hdr->current_hop_limit;*/ 00609 00610 /* Update flags in local entry (incl. preference). */ 00611 default_router_list[i].flags = ra_hdr->flags; 00612 00613 /* Offset to options. */ 00614 offset = sizeof(struct ra_header); 00615 00616 /* Process each option. */ 00617 while ((p->tot_len - offset) > 0) { 00618 if (p->len == p->tot_len) { 00619 /* no need to copy from contiguous pbuf */ 00620 buffer = &((u8_t*)p->payload)[offset]; 00621 } else { 00622 buffer = nd6_ra_buffer; 00623 if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) { 00624 pbuf_free(p); 00625 ND6_STATS_INC(nd6.lenerr); 00626 ND6_STATS_INC(nd6.drop); 00627 return; 00628 } 00629 } 00630 if (buffer[1] == 0) { 00631 /* zero-length extension. drop packet */ 00632 pbuf_free(p); 00633 ND6_STATS_INC(nd6.lenerr); 00634 ND6_STATS_INC(nd6.drop); 00635 return; 00636 } 00637 switch (buffer[0]) { 00638 case ND6_OPTION_TYPE_SOURCE_LLADDR: 00639 { 00640 struct lladdr_option *lladdr_opt; 00641 lladdr_opt = (struct lladdr_option *)buffer; 00642 if ((default_router_list[i].neighbor_entry != NULL) && 00643 (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { 00644 SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); 00645 default_router_list[i].neighbor_entry->state = ND6_REACHABLE; 00646 default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; 00647 } 00648 break; 00649 } 00650 case ND6_OPTION_TYPE_MTU: 00651 { 00652 struct mtu_option *mtu_opt; 00653 mtu_opt = (struct mtu_option *)buffer; 00654 if (lwip_htonl(mtu_opt->mtu) >= 1280) { 00655 #if LWIP_ND6_ALLOW_RA_UPDATES 00656 inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); 00657 #endif /* LWIP_ND6_ALLOW_RA_UPDATES */ 00658 } 00659 break; 00660 } 00661 case ND6_OPTION_TYPE_PREFIX_INFO: 00662 { 00663 struct prefix_option *prefix_opt; 00664 ip6_addr_t prefix_addr; 00665 00666 prefix_opt = (struct prefix_option *)buffer; 00667 00668 /* Get a memory-aligned copy of the prefix. */ 00669 ip6_addr_set(&prefix_addr, &(prefix_opt->prefix)); 00670 00671 if (!ip6_addr_islinklocal(&prefix_addr)) { 00672 if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) && 00673 (prefix_opt->prefix_length == 64)) { 00674 /* Add to on-link prefix list. */ 00675 u32_t valid_life; 00676 s8_t prefix; 00677 00678 valid_life = lwip_htonl(prefix_opt->valid_lifetime); 00679 00680 /* find cache entry for this prefix. */ 00681 prefix = nd6_get_onlink_prefix(&prefix_addr, inp); 00682 if (prefix < 0 && valid_life > 0) { 00683 /* Create a new cache entry. */ 00684 prefix = nd6_new_onlink_prefix(&prefix_addr, inp); 00685 } 00686 if (prefix >= 0) { 00687 prefix_list[prefix].invalidation_timer = valid_life; 00688 } 00689 } 00690 #if LWIP_IPV6_AUTOCONFIG 00691 if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { 00692 /* Perform processing for autoconfiguration. */ 00693 nd6_process_autoconfig_prefix(inp, prefix_opt, &prefix_addr); 00694 } 00695 #endif /* LWIP_IPV6_AUTOCONFIG */ 00696 } 00697 00698 break; 00699 } 00700 case ND6_OPTION_TYPE_ROUTE_INFO: 00701 /* @todo implement preferred routes. 00702 struct route_option * route_opt; 00703 route_opt = (struct route_option *)buffer;*/ 00704 00705 break; 00706 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS 00707 case ND6_OPTION_TYPE_RDNSS: 00708 { 00709 u8_t num, n; 00710 struct rdnss_option * rdnss_opt; 00711 00712 rdnss_opt = (struct rdnss_option *)buffer; 00713 num = (rdnss_opt->length - 1) / 2; 00714 for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { 00715 ip_addr_t rdnss_address; 00716 00717 /* Get a memory-aligned copy of the prefix. */ 00718 ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]); 00719 00720 if (htonl(rdnss_opt->lifetime) > 0) { 00721 /* TODO implement Lifetime > 0 */ 00722 dns_setserver(rdnss_server_idx++, &rdnss_address); 00723 } else { 00724 /* TODO implement DNS removal in dns.c */ 00725 u8_t s; 00726 for (s = 0; s < DNS_MAX_SERVERS; s++) { 00727 const ip_addr_t *addr = dns_getserver(s); 00728 if(ip_addr_cmp(addr, &rdnss_address)) { 00729 dns_setserver(s, NULL); 00730 } 00731 } 00732 } 00733 } 00734 break; 00735 } 00736 #endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ 00737 default: 00738 /* Unrecognized option, abort. */ 00739 ND6_STATS_INC(nd6.proterr); 00740 break; 00741 } 00742 /* option length is checked earlier to be non-zero to make sure loop ends */ 00743 offset += 8 * ((u16_t)buffer[1]); 00744 } 00745 00746 break; /* ICMP6_TYPE_RA */ 00747 } 00748 case ICMP6_TYPE_RD: /* Redirect */ 00749 { 00750 struct redirect_header *redir_hdr; 00751 struct lladdr_option *lladdr_opt; 00752 ip6_addr_t destination_address, target_address; 00753 00754 /* Check that Redir header fits in packet. */ 00755 if (p->len < sizeof(struct redirect_header)) { 00756 /* @todo debug message */ 00757 pbuf_free(p); 00758 ND6_STATS_INC(nd6.lenerr); 00759 ND6_STATS_INC(nd6.drop); 00760 return; 00761 } 00762 00763 redir_hdr = (struct redirect_header *)p->payload; 00764 00765 /* Copy original destination address, to have an aligned copy. */ 00766 ip6_addr_set(&destination_address, &(redir_hdr->destination_address)); 00767 00768 /* Check a subset of the other RFC 4861 Sec. 8.1 requirements. */ 00769 if (!ip6_addr_islinklocal(ip6_current_src_addr()) || 00770 IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || 00771 redir_hdr->code != 0 || ip6_addr_ismulticast(&destination_address)) { 00772 pbuf_free(p); 00773 ND6_STATS_INC(nd6.proterr); 00774 ND6_STATS_INC(nd6.drop); 00775 return; 00776 } 00777 00778 /* @todo RFC MUST: IP source address equals first-hop router for destination_address */ 00779 /* @todo RFC MUST: ICMP target address is either link-local address or same as destination_address */ 00780 /* @todo RFC MUST: all included options have a length greater than zero */ 00781 00782 if (p->len >= (sizeof(struct redirect_header) + 2)) { 00783 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); 00784 if (p->len < (sizeof(struct redirect_header) + (lladdr_opt->length << 3))) { 00785 lladdr_opt = NULL; 00786 } 00787 } else { 00788 lladdr_opt = NULL; 00789 } 00790 00791 /* Find dest address in cache */ 00792 i = nd6_find_destination_cache_entry(&destination_address); 00793 if (i < 0) { 00794 /* Destination not in cache, drop packet. */ 00795 pbuf_free(p); 00796 return; 00797 } 00798 00799 /* Set the new target address. */ 00800 ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); 00801 00802 /* If Link-layer address of other router is given, try to add to neighbor cache. */ 00803 if (lladdr_opt != NULL) { 00804 if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { 00805 /* Copy target address to current source address, to have an aligned copy. */ 00806 ip6_addr_set(&target_address, &(redir_hdr->target_address)); 00807 00808 i = nd6_find_neighbor_cache_entry(&target_address); 00809 if (i < 0) { 00810 i = nd6_new_neighbor_cache_entry(); 00811 if (i >= 0) { 00812 neighbor_cache[i].netif = inp; 00813 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 00814 ip6_addr_set(&(neighbor_cache[i].next_hop_address), &target_address); 00815 00816 /* Receiving a message does not prove reachability: only in one direction. 00817 * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ 00818 neighbor_cache[i].state = ND6_DELAY; 00819 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 00820 } 00821 } 00822 if (i >= 0) { 00823 if (neighbor_cache[i].state == ND6_INCOMPLETE) { 00824 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); 00825 /* Receiving a message does not prove reachability: only in one direction. 00826 * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ 00827 neighbor_cache[i].state = ND6_DELAY; 00828 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 00829 } 00830 } 00831 } 00832 } 00833 break; /* ICMP6_TYPE_RD */ 00834 } 00835 case ICMP6_TYPE_PTB: /* Packet too big */ 00836 { 00837 struct icmp6_hdr *icmp6hdr; /* Packet too big message */ 00838 struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ 00839 u32_t pmtu; 00840 ip6_addr_t tmp; 00841 00842 /* Check that ICMPv6 header + IPv6 header fit in payload */ 00843 if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { 00844 /* drop short packets */ 00845 pbuf_free(p); 00846 ND6_STATS_INC(nd6.lenerr); 00847 ND6_STATS_INC(nd6.drop); 00848 return; 00849 } 00850 00851 icmp6hdr = (struct icmp6_hdr *)p->payload; 00852 ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); 00853 00854 /* Copy original destination address to current source address, to have an aligned copy. */ 00855 ip6_addr_set(&tmp, &(ip6hdr->dest)); 00856 00857 /* Look for entry in destination cache. */ 00858 i = nd6_find_destination_cache_entry(&tmp); 00859 if (i < 0) { 00860 /* Destination not in cache, drop packet. */ 00861 pbuf_free(p); 00862 return; 00863 } 00864 00865 /* Change the Path MTU. */ 00866 pmtu = lwip_htonl(icmp6hdr->data); 00867 destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); 00868 00869 break; /* ICMP6_TYPE_PTB */ 00870 } 00871 00872 default: 00873 ND6_STATS_INC(nd6.proterr); 00874 ND6_STATS_INC(nd6.drop); 00875 break; /* default */ 00876 } 00877 00878 pbuf_free(p); 00879 } 00880 00881 00882 /** 00883 * Periodic timer for Neighbor discovery functions: 00884 * 00885 * - Update neighbor reachability states 00886 * - Update destination cache entries age 00887 * - Update invalidation timers of default routers and on-link prefixes 00888 * - Update lifetimes of our addresses 00889 * - Perform duplicate address detection (DAD) for our addresses 00890 * - Send router solicitations 00891 */ 00892 void 00893 nd6_tmr(void) 00894 { 00895 s8_t i; 00896 struct netif *netif; 00897 00898 /* Process neighbor entries. */ 00899 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 00900 switch (neighbor_cache[i].state) { 00901 case ND6_INCOMPLETE: 00902 if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && 00903 (!neighbor_cache[i].isrouter)) { 00904 /* Retries exceeded. */ 00905 nd6_free_neighbor_cache_entry(i); 00906 } else { 00907 /* Send a NS for this entry. */ 00908 neighbor_cache[i].counter.probes_sent++; 00909 nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); 00910 } 00911 break; 00912 case ND6_REACHABLE: 00913 /* Send queued packets, if any are left. Should have been sent already. */ 00914 if (neighbor_cache[i].q != NULL) { 00915 nd6_send_q(i); 00916 } 00917 if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { 00918 /* Change to stale state. */ 00919 neighbor_cache[i].state = ND6_STALE; 00920 neighbor_cache[i].counter.stale_time = 0; 00921 } else { 00922 neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; 00923 } 00924 break; 00925 case ND6_STALE: 00926 neighbor_cache[i].counter.stale_time++; 00927 break; 00928 case ND6_DELAY: 00929 if (neighbor_cache[i].counter.delay_time <= 1) { 00930 /* Change to PROBE state. */ 00931 neighbor_cache[i].state = ND6_PROBE; 00932 neighbor_cache[i].counter.probes_sent = 0; 00933 } else { 00934 neighbor_cache[i].counter.delay_time--; 00935 } 00936 break; 00937 case ND6_PROBE: 00938 if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && 00939 (!neighbor_cache[i].isrouter)) { 00940 /* Retries exceeded. */ 00941 nd6_free_neighbor_cache_entry(i); 00942 } else { 00943 /* Send a NS for this entry. */ 00944 neighbor_cache[i].counter.probes_sent++; 00945 nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0); 00946 } 00947 break; 00948 case ND6_NO_ENTRY: 00949 default: 00950 /* Do nothing. */ 00951 break; 00952 } 00953 } 00954 00955 /* Process destination entries. */ 00956 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 00957 destination_cache[i].age++; 00958 } 00959 00960 /* Process router entries. */ 00961 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 00962 if (default_router_list[i].neighbor_entry != NULL) { 00963 /* Active entry. */ 00964 if (default_router_list[i].invalidation_timer <= ND6_TMR_INTERVAL / 1000) { 00965 /* No more than 1 second remaining. Clear this entry. Also clear any of 00966 * its destination cache entries, as per RFC 4861 Sec. 5.3 and 6.3.5. */ 00967 s8_t j; 00968 for (j = 0; j < LWIP_ND6_NUM_DESTINATIONS; j++) { 00969 if (ip6_addr_cmp(&destination_cache[j].next_hop_addr, 00970 &default_router_list[i].neighbor_entry->next_hop_address)) { 00971 ip6_addr_set_any(&destination_cache[j].destination_addr); 00972 } 00973 } 00974 default_router_list[i].neighbor_entry->isrouter = 0; 00975 default_router_list[i].neighbor_entry = NULL; 00976 default_router_list[i].invalidation_timer = 0; 00977 default_router_list[i].flags = 0; 00978 } else { 00979 default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; 00980 } 00981 } 00982 } 00983 00984 /* Process prefix entries. */ 00985 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { 00986 if (prefix_list[i].netif != NULL) { 00987 if (prefix_list[i].invalidation_timer <= ND6_TMR_INTERVAL / 1000) { 00988 /* Entry timed out, remove it */ 00989 prefix_list[i].invalidation_timer = 0; 00990 prefix_list[i].netif = NULL; 00991 } else { 00992 prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; 00993 } 00994 } 00995 } 00996 00997 /* Process our own addresses, updating address lifetimes and/or DAD state. */ 00998 for (netif = netif_list; netif != NULL; netif = netif->next) { 00999 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { 01000 u8_t addr_state; 01001 #if LWIP_IPV6_ADDRESS_LIFETIMES 01002 /* Step 1: update address lifetimes (valid and preferred). */ 01003 addr_state = netif_ip6_addr_state(netif, i); 01004 /* RFC 4862 is not entirely clear as to whether address lifetimes affect 01005 * tentative addresses, and is even less clear as to what should happen 01006 * with duplicate addresses. We choose to track and update lifetimes for 01007 * both those types, although for different reasons: 01008 * - for tentative addresses, the line of thought of Sec. 5.7 combined 01009 * with the potentially long period that an address may be in tentative 01010 * state (due to the interface being down) suggests that lifetimes 01011 * should be independent of external factors which would include DAD; 01012 * - for duplicate addresses, retiring them early could result in a new 01013 * but unwanted attempt at marking them as valid, while retiring them 01014 * late/never could clog up address slots on the netif. 01015 * As a result, we may end up expiring addresses of either type here. 01016 */ 01017 if (!ip6_addr_isinvalid(addr_state) && 01018 !netif_ip6_addr_isstatic(netif, i)) { 01019 u32_t life = netif_ip6_addr_valid_life(netif, i); 01020 if (life <= ND6_TMR_INTERVAL / 1000) { 01021 /* The address has expired. */ 01022 netif_ip6_addr_set_valid_life(netif, i, 0); 01023 netif_ip6_addr_set_pref_life(netif, i, 0); 01024 netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID); 01025 } else { 01026 if (!ip6_addr_life_isinfinite(life)) { 01027 life -= ND6_TMR_INTERVAL / 1000; 01028 LWIP_ASSERT("bad valid lifetime", life != IP6_ADDR_LIFE_STATIC); 01029 netif_ip6_addr_set_valid_life(netif, i, life); 01030 } 01031 /* The address is still here. Update the preferred lifetime too. */ 01032 life = netif_ip6_addr_pref_life(netif, i); 01033 if (life <= ND6_TMR_INTERVAL / 1000) { 01034 /* This case must also trigger if 'life' was already zero, so as to 01035 * deal correctly with advertised preferred-lifetime reductions. */ 01036 netif_ip6_addr_set_pref_life(netif, i, 0); 01037 if (addr_state == IP6_ADDR_PREFERRED) 01038 netif_ip6_addr_set_state(netif, i, IP6_ADDR_DEPRECATED); 01039 } else if (!ip6_addr_life_isinfinite(life)) { 01040 life -= ND6_TMR_INTERVAL / 1000; 01041 netif_ip6_addr_set_pref_life(netif, i, life); 01042 } 01043 } 01044 } 01045 /* The address state may now have changed, so reobtain it next. */ 01046 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */ 01047 /* Step 2: update DAD state. */ 01048 addr_state = netif_ip6_addr_state(netif, i); 01049 if (ip6_addr_istentative(addr_state)) { 01050 if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { 01051 /* No NA received in response. Mark address as valid. For dynamic 01052 * addresses with an expired preferred lifetime, the state is set to 01053 * deprecated right away. That should almost never happen, though. */ 01054 addr_state = IP6_ADDR_PREFERRED; 01055 #if LWIP_IPV6_ADDRESS_LIFETIMES 01056 if (!netif_ip6_addr_isstatic(netif, i) && 01057 netif_ip6_addr_pref_life(netif, i) == 0) { 01058 addr_state = IP6_ADDR_DEPRECATED; 01059 } 01060 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */ 01061 netif_ip6_addr_set_state(netif, i, addr_state); 01062 } else if (netif_is_up(netif) && netif_is_link_up(netif)) { 01063 /* tentative: set next state by increasing by one */ 01064 netif_ip6_addr_set_state(netif, i, addr_state + 1); 01065 /* Send a NS for this address. Use the unspecified address as source 01066 * address in all cases (RFC 4862 Sec. 5.4.2), not in the least 01067 * because as it is, we only consider multicast replies for DAD. */ 01068 nd6_send_ns(netif, netif_ip6_addr(netif, i), 01069 ND6_SEND_FLAG_MULTICAST_DEST | ND6_SEND_FLAG_ANY_SRC); 01070 } 01071 } 01072 } 01073 } 01074 01075 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 01076 /* Send router solicitation messages, if necessary. */ 01077 for (netif = netif_list; netif != NULL; netif = netif->next) { 01078 if ((netif->rs_count > 0) && netif_is_up(netif) && 01079 netif_is_link_up(netif) && 01080 !ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)) && 01081 !ip6_addr_isduplicated(netif_ip6_addr_state(netif, 0))) { 01082 if (nd6_send_rs(netif) == ERR_OK) { 01083 netif->rs_count--; 01084 } 01085 } 01086 } 01087 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 01088 01089 } 01090 01091 /** Send a neighbor solicitation message for a specific neighbor cache entry 01092 * 01093 * @param entry the neightbor cache entry for wich to send the message 01094 * @param flags one of ND6_SEND_FLAG_* 01095 */ 01096 static void 01097 nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags) 01098 { 01099 nd6_send_ns(entry->netif, &entry->next_hop_address, flags); 01100 } 01101 01102 /** 01103 * Send a neighbor solicitation message 01104 * 01105 * @param netif the netif on which to send the message 01106 * @param target_addr the IPv6 target address for the ND message 01107 * @param flags one of ND6_SEND_FLAG_* 01108 */ 01109 static void 01110 nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) 01111 { 01112 struct ns_header *ns_hdr; 01113 struct pbuf *p; 01114 const ip6_addr_t *src_addr; 01115 u16_t lladdr_opt_len; 01116 01117 if (!(flags & ND6_SEND_FLAG_ANY_SRC) && 01118 ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { 01119 /* Use link-local address as source address. */ 01120 src_addr = netif_ip6_addr(netif, 0); 01121 /* calculate option length (in 8-byte-blocks) */ 01122 lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3; 01123 } else { 01124 src_addr = IP6_ADDR_ANY6; 01125 /* Option "MUST NOT be included when the source IP address is the unspecified address." */ 01126 lladdr_opt_len = 0; 01127 } 01128 01129 /* Allocate a packet. */ 01130 p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + (lladdr_opt_len << 3), PBUF_RAM); 01131 if (p == NULL) { 01132 ND6_STATS_INC(nd6.memerr); 01133 return; 01134 } 01135 01136 /* Set fields. */ 01137 ns_hdr = (struct ns_header *)p->payload; 01138 01139 ns_hdr->type = ICMP6_TYPE_NS; 01140 ns_hdr->code = 0; 01141 ns_hdr->chksum = 0; 01142 ns_hdr->reserved = 0; 01143 ip6_addr_set(&(ns_hdr->target_address), target_addr); 01144 01145 if (lladdr_opt_len != 0) { 01146 struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); 01147 lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; 01148 lladdr_opt->length = (u8_t)lladdr_opt_len; 01149 SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); 01150 } 01151 01152 /* Generate the solicited node address for the target address. */ 01153 if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { 01154 ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); 01155 target_addr = &multicast_address; 01156 } 01157 01158 #if CHECKSUM_GEN_ICMP6 01159 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { 01160 ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, 01161 target_addr); 01162 } 01163 #endif /* CHECKSUM_GEN_ICMP6 */ 01164 01165 /* Send the packet out. */ 01166 ND6_STATS_INC(nd6.xmit); 01167 ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr, 01168 ND6_HOPLIM, 0, IP6_NEXTH_ICMP6, netif); 01169 pbuf_free(p); 01170 } 01171 01172 /** 01173 * Send a neighbor advertisement message 01174 * 01175 * @param netif the netif on which to send the message 01176 * @param target_addr the IPv6 target address for the ND message 01177 * @param flags one of ND6_SEND_FLAG_* 01178 */ 01179 static void 01180 nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) 01181 { 01182 struct na_header *na_hdr; 01183 struct lladdr_option *lladdr_opt; 01184 struct pbuf *p; 01185 const ip6_addr_t *src_addr; 01186 const ip6_addr_t *dest_addr; 01187 u16_t lladdr_opt_len; 01188 01189 /* Use link-local address as source address. */ 01190 /* src_addr = netif_ip6_addr(netif, 0); */ 01191 /* Use target address as source address. */ 01192 src_addr = target_addr; 01193 01194 /* Allocate a packet. */ 01195 lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); 01196 p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + (lladdr_opt_len << 3), PBUF_RAM); 01197 if (p == NULL) { 01198 ND6_STATS_INC(nd6.memerr); 01199 return; 01200 } 01201 01202 /* Set fields. */ 01203 na_hdr = (struct na_header *)p->payload; 01204 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); 01205 01206 na_hdr->type = ICMP6_TYPE_NA; 01207 na_hdr->code = 0; 01208 na_hdr->chksum = 0; 01209 na_hdr->flags = flags & 0xf0; 01210 na_hdr->reserved[0] = 0; 01211 na_hdr->reserved[1] = 0; 01212 na_hdr->reserved[2] = 0; 01213 ip6_addr_set(&(na_hdr->target_address), target_addr); 01214 01215 lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; 01216 lladdr_opt->length = (u8_t)lladdr_opt_len; 01217 SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); 01218 01219 /* Generate the solicited node address for the target address. */ 01220 if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { 01221 ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); 01222 dest_addr = &multicast_address; 01223 } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { 01224 ip6_addr_set_allnodes_linklocal(&multicast_address); 01225 dest_addr = &multicast_address; 01226 } else { 01227 dest_addr = ip6_current_src_addr(); 01228 } 01229 01230 #if CHECKSUM_GEN_ICMP6 01231 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { 01232 na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, 01233 dest_addr); 01234 } 01235 #endif /* CHECKSUM_GEN_ICMP6 */ 01236 01237 /* Send the packet out. */ 01238 ND6_STATS_INC(nd6.xmit); 01239 ip6_output_if(p, src_addr, dest_addr, 01240 ND6_HOPLIM, 0, IP6_NEXTH_ICMP6, netif); 01241 pbuf_free(p); 01242 } 01243 01244 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 01245 /** 01246 * Send a router solicitation message 01247 * 01248 * @param netif the netif on which to send the message 01249 */ 01250 static err_t 01251 nd6_send_rs(struct netif *netif) 01252 { 01253 struct rs_header *rs_hdr; 01254 struct lladdr_option *lladdr_opt; 01255 struct pbuf *p; 01256 const ip6_addr_t *src_addr; 01257 err_t err; 01258 u16_t lladdr_opt_len = 0; 01259 01260 /* Link-local source address, or unspecified address? */ 01261 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { 01262 src_addr = netif_ip6_addr(netif, 0); 01263 } else { 01264 src_addr = IP6_ADDR_ANY6; 01265 } 01266 01267 /* Generate the all routers target address. */ 01268 ip6_addr_set_allrouters_linklocal(&multicast_address); 01269 01270 /* Allocate a packet. */ 01271 if (src_addr != IP6_ADDR_ANY6 && netif->hwaddr_len) { 01272 lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); 01273 } 01274 p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM); 01275 if (p == NULL) { 01276 ND6_STATS_INC(nd6.memerr); 01277 return ERR_BUF; 01278 } 01279 01280 /* Set fields. */ 01281 rs_hdr = (struct rs_header *)p->payload; 01282 01283 rs_hdr->type = ICMP6_TYPE_RS; 01284 rs_hdr->code = 0; 01285 rs_hdr->chksum = 0; 01286 rs_hdr->reserved = 0; 01287 01288 if (src_addr != IP6_ADDR_ANY6 && lladdr_opt_len) { 01289 /* Include our hw address. */ 01290 lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); 01291 lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; 01292 lladdr_opt->length = (u8_t)lladdr_opt_len; 01293 SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); 01294 } 01295 01296 #if CHECKSUM_GEN_ICMP6 01297 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { 01298 rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, 01299 &multicast_address); 01300 } 01301 #endif /* CHECKSUM_GEN_ICMP6 */ 01302 01303 /* Send the packet out. */ 01304 ND6_STATS_INC(nd6.xmit); 01305 01306 err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address, 01307 ND6_HOPLIM, 0, IP6_NEXTH_ICMP6, netif); 01308 pbuf_free(p); 01309 01310 return err; 01311 } 01312 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 01313 01314 /** 01315 * Search for a neighbor cache entry 01316 * 01317 * @param ip6addr the IPv6 address of the neighbor 01318 * @return The neighbor cache entry index that matched, -1 if no 01319 * entry is found 01320 */ 01321 static s8_t 01322 nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr) 01323 { 01324 s8_t i; 01325 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 01326 if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { 01327 return i; 01328 } 01329 } 01330 return -1; 01331 } 01332 01333 /** 01334 * Create a new neighbor cache entry. 01335 * 01336 * If no unused entry is found, will try to recycle an old entry 01337 * according to ad-hoc "age" heuristic. 01338 * 01339 * @return The neighbor cache entry index that was created, -1 if no 01340 * entry could be created 01341 */ 01342 static s8_t 01343 nd6_new_neighbor_cache_entry(void) 01344 { 01345 s8_t i; 01346 s8_t j; 01347 u32_t time; 01348 01349 01350 /* First, try to find an empty entry. */ 01351 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 01352 if (neighbor_cache[i].state == ND6_NO_ENTRY) { 01353 return i; 01354 } 01355 } 01356 01357 /* We need to recycle an entry. in general, do not recycle if it is a router. */ 01358 01359 /* Next, try to find a Stale entry. */ 01360 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 01361 if ((neighbor_cache[i].state == ND6_STALE) && 01362 (!neighbor_cache[i].isrouter)) { 01363 nd6_free_neighbor_cache_entry(i); 01364 return i; 01365 } 01366 } 01367 01368 /* Next, try to find a Probe entry. */ 01369 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 01370 if ((neighbor_cache[i].state == ND6_PROBE) && 01371 (!neighbor_cache[i].isrouter)) { 01372 nd6_free_neighbor_cache_entry(i); 01373 return i; 01374 } 01375 } 01376 01377 /* Next, try to find a Delayed entry. */ 01378 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 01379 if ((neighbor_cache[i].state == ND6_DELAY) && 01380 (!neighbor_cache[i].isrouter)) { 01381 nd6_free_neighbor_cache_entry(i); 01382 return i; 01383 } 01384 } 01385 01386 /* Next, try to find the oldest reachable entry. */ 01387 time = 0xfffffffful; 01388 j = -1; 01389 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 01390 if ((neighbor_cache[i].state == ND6_REACHABLE) && 01391 (!neighbor_cache[i].isrouter)) { 01392 if (neighbor_cache[i].counter.reachable_time < time) { 01393 j = i; 01394 time = neighbor_cache[i].counter.reachable_time; 01395 } 01396 } 01397 } 01398 if (j >= 0) { 01399 nd6_free_neighbor_cache_entry(j); 01400 return j; 01401 } 01402 01403 /* Next, find oldest incomplete entry without queued packets. */ 01404 time = 0; 01405 j = -1; 01406 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 01407 if ( 01408 (neighbor_cache[i].q == NULL) && 01409 (neighbor_cache[i].state == ND6_INCOMPLETE) && 01410 (!neighbor_cache[i].isrouter)) { 01411 if (neighbor_cache[i].counter.probes_sent >= time) { 01412 j = i; 01413 time = neighbor_cache[i].counter.probes_sent; 01414 } 01415 } 01416 } 01417 if (j >= 0) { 01418 nd6_free_neighbor_cache_entry(j); 01419 return j; 01420 } 01421 01422 /* Next, find oldest incomplete entry with queued packets. */ 01423 time = 0; 01424 j = -1; 01425 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 01426 if ((neighbor_cache[i].state == ND6_INCOMPLETE) && 01427 (!neighbor_cache[i].isrouter)) { 01428 if (neighbor_cache[i].counter.probes_sent >= time) { 01429 j = i; 01430 time = neighbor_cache[i].counter.probes_sent; 01431 } 01432 } 01433 } 01434 if (j >= 0) { 01435 nd6_free_neighbor_cache_entry(j); 01436 return j; 01437 } 01438 01439 /* No more entries to try. */ 01440 return -1; 01441 } 01442 01443 /** 01444 * Will free any resources associated with a neighbor cache 01445 * entry, and will mark it as unused. 01446 * 01447 * @param i the neighbor cache entry index to free 01448 */ 01449 static void 01450 nd6_free_neighbor_cache_entry(s8_t i) 01451 { 01452 if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { 01453 return; 01454 } 01455 if (neighbor_cache[i].isrouter) { 01456 /* isrouter needs to be cleared before deleting a neighbor cache entry */ 01457 return; 01458 } 01459 01460 /* Free any queued packets. */ 01461 if (neighbor_cache[i].q != NULL) { 01462 nd6_free_q(neighbor_cache[i].q); 01463 neighbor_cache[i].q = NULL; 01464 } 01465 01466 neighbor_cache[i].state = ND6_NO_ENTRY; 01467 neighbor_cache[i].isrouter = 0; 01468 neighbor_cache[i].netif = NULL; 01469 neighbor_cache[i].counter.reachable_time = 0; 01470 ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); 01471 } 01472 01473 /** 01474 * Search for a destination cache entry 01475 * 01476 * @param ip6addr the IPv6 address of the destination 01477 * @return The destination cache entry index that matched, -1 if no 01478 * entry is found 01479 */ 01480 static s8_t 01481 nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) 01482 { 01483 s8_t i; 01484 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 01485 if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { 01486 return i; 01487 } 01488 } 01489 return -1; 01490 } 01491 01492 /** 01493 * Create a new destination cache entry. If no unused entry is found, 01494 * will recycle oldest entry. 01495 * 01496 * @return The destination cache entry index that was created, -1 if no 01497 * entry was created 01498 */ 01499 static s8_t 01500 nd6_new_destination_cache_entry(void) 01501 { 01502 s8_t i, j; 01503 u32_t age; 01504 01505 /* Find an empty entry. */ 01506 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 01507 if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { 01508 return i; 01509 } 01510 } 01511 01512 /* Find oldest entry. */ 01513 age = 0; 01514 j = LWIP_ND6_NUM_DESTINATIONS - 1; 01515 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 01516 if (destination_cache[i].age > age) { 01517 j = i; 01518 } 01519 } 01520 01521 return j; 01522 } 01523 01524 /** 01525 * Clear the destination cache. 01526 * 01527 * This operation may be necessary for consistency in the light of changing 01528 * local addresses and/or use of the gateway hook. 01529 */ 01530 void 01531 nd6_clear_destination_cache(void) 01532 { 01533 int i; 01534 01535 for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { 01536 ip6_addr_set_any(&destination_cache[i].destination_addr); 01537 } 01538 } 01539 01540 /** 01541 * Determine whether an address matches an on-link prefix or the subnet of a 01542 * statically assigned address. 01543 * 01544 * @param ip6addr the IPv6 address to match 01545 * @return 1 if the address is on-link, 0 otherwise 01546 */ 01547 static s8_t 01548 nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) 01549 { 01550 s8_t i; 01551 01552 /* Check to see if the address matches an on-link prefix. */ 01553 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { 01554 if ((prefix_list[i].netif == netif) && 01555 (prefix_list[i].invalidation_timer > 0) && 01556 ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { 01557 return 1; 01558 } 01559 } 01560 /* Check to see if address prefix matches a manually configured (= static) 01561 * address. Static addresses have an implied /64 subnet assignment. Dynamic 01562 * addresses (from autoconfiguration) have no implied subnet assignment, and 01563 * are thus effectively /128 assignments. See RFC 5942 for more on this. */ 01564 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 01565 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 01566 netif_ip6_addr_isstatic(netif, i) && 01567 ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { 01568 return 1; 01569 } 01570 } 01571 return 0; 01572 } 01573 01574 /** 01575 * Select a default router for a destination. 01576 * 01577 * This function is used both for routing and for finding a next-hop target for 01578 * a packet. In the former case, the given netif is NULL, and the returned 01579 * router entry must be for a netif suitable for sending packets (up, link up). 01580 * In the latter case, the given netif is not NULL and restricts router choice. 01581 * 01582 * @param ip6addr the destination address 01583 * @param netif the netif for the outgoing packet, if known 01584 * @return the default router entry index, or -1 if no suitable 01585 * router is found 01586 */ 01587 static s8_t 01588 nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) 01589 { 01590 struct netif *router_netif; 01591 s8_t i, j, valid_router; 01592 static s8_t last_router; 01593 01594 LWIP_UNUSED_ARG(ip6addr); /* @todo match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ 01595 01596 /* @todo: implement default router preference */ 01597 01598 /* Look for valid routers. A reachable router is preferred. */ 01599 valid_router = -1; 01600 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 01601 /* Is the router netif both set and apppropriate? */ 01602 if (default_router_list[i].neighbor_entry != NULL) { 01603 router_netif = default_router_list[i].neighbor_entry->netif; 01604 if ((router_netif != NULL) && (netif != NULL ? netif == router_netif : 01605 (netif_is_up(router_netif) && netif_is_link_up(router_netif)))) { 01606 /* Is the router valid, i.e., reachable or probably reachable as per 01607 * RFC 4861 Sec. 6.3.6? Note that we will never return a router that 01608 * has no neighbor cache entry, due to the netif association tests. */ 01609 if (default_router_list[i].neighbor_entry->state != ND6_INCOMPLETE) { 01610 /* Is the router known to be reachable? */ 01611 if (default_router_list[i].neighbor_entry->state == ND6_REACHABLE) { 01612 return i; /* valid and reachable - done! */ 01613 } else if (valid_router < 0) { 01614 valid_router = i; /* valid but not known to be reachable */ 01615 } 01616 } 01617 } 01618 } 01619 } 01620 if (valid_router >= 0) { 01621 return valid_router; 01622 } 01623 01624 /* Look for any router for which we have any information at all. */ 01625 /* last_router is used for round-robin selection of incomplete routers, as 01626 * recommended in RFC 4861 Sec. 6.3.6 point (2). Advance only when picking a 01627 * route, to select the same router as next-hop target in the common case. */ 01628 if ((netif == NULL) && (++last_router >= LWIP_ND6_NUM_ROUTERS)) { 01629 last_router = 0; 01630 } 01631 i = last_router; 01632 for (j = 0; j < LWIP_ND6_NUM_ROUTERS; j++) { 01633 if (default_router_list[i].neighbor_entry != NULL) { 01634 router_netif = default_router_list[i].neighbor_entry->netif; 01635 if ((router_netif != NULL) && (netif != NULL ? netif == router_netif : 01636 (netif_is_up(router_netif) && netif_is_link_up(router_netif)))) { 01637 return i; 01638 } 01639 } 01640 if (++i >= LWIP_ND6_NUM_ROUTERS) { 01641 i = 0; 01642 } 01643 } 01644 01645 /* no suitable router found. */ 01646 return -1; 01647 } 01648 01649 /** 01650 * Find a router-announced route to the given destination. This route may be 01651 * based on an on-link prefix or a default router. 01652 * 01653 * If a suitable route is found, the returned netif is guaranteed to be in a 01654 * suitable state (up, link up) to be used for packet transmission. 01655 * 01656 * @param ip6addr the destination IPv6 address 01657 * @return the netif to use for the destination, or NULL if none found 01658 */ 01659 struct netif * 01660 nd6_find_route(const ip6_addr_t *ip6addr) 01661 { 01662 struct netif *netif; 01663 s8_t i; 01664 01665 /* @todo decide if it makes sense to check the destination cache first */ 01666 01667 /* Check if there is a matching on-link prefix. There may be multiple 01668 * matches. Pick the first one that is associated with a suitable netif. */ 01669 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { 01670 netif = prefix_list[i].netif; 01671 if ((netif != NULL) && ip6_addr_netcmp(&prefix_list[i].prefix, ip6addr) && 01672 netif_is_up(netif) && netif_is_link_up(netif)) { 01673 return netif; 01674 } 01675 } 01676 01677 /* No on-link prefix match. Find a router that can forward the packet. */ 01678 i = nd6_select_router(ip6addr, NULL); 01679 if (i >= 0) { 01680 LWIP_ASSERT("selected router must have a neighbor entry", 01681 default_router_list[i].neighbor_entry != NULL); 01682 return default_router_list[i].neighbor_entry->netif; 01683 } 01684 01685 return NULL; 01686 } 01687 01688 /** 01689 * Find an entry for a default router. 01690 * 01691 * @param router_addr the IPv6 address of the router 01692 * @param netif the netif on which the router is found, if known 01693 * @return the index of the router entry, or -1 if not found 01694 */ 01695 static s8_t 01696 nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif) 01697 { 01698 s8_t i; 01699 01700 /* Look for router. */ 01701 for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { 01702 if ((default_router_list[i].neighbor_entry != NULL) && 01703 ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && 01704 ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { 01705 return i; 01706 } 01707 } 01708 01709 /* router not found. */ 01710 return -1; 01711 } 01712 01713 /** 01714 * Create a new entry for a default router. 01715 * 01716 * @param router_addr the IPv6 address of the router 01717 * @param netif the netif on which the router is connected, if known 01718 * @return the index on the router table, or -1 if could not be created 01719 */ 01720 static s8_t 01721 nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) 01722 { 01723 s8_t router_index; 01724 s8_t free_router_index; 01725 s8_t neighbor_index; 01726 01727 /* Do we have a neighbor entry for this router? */ 01728 neighbor_index = nd6_find_neighbor_cache_entry(router_addr); 01729 if (neighbor_index < 0) { 01730 /* Create a neighbor entry for this router. */ 01731 neighbor_index = nd6_new_neighbor_cache_entry(); 01732 if (neighbor_index < 0) { 01733 /* Could not create neighbor entry for this router. */ 01734 return -1; 01735 } 01736 ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); 01737 neighbor_cache[neighbor_index].netif = netif; 01738 neighbor_cache[neighbor_index].q = NULL; 01739 if (netif->hwaddr_len) { 01740 neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; 01741 neighbor_cache[neighbor_index].counter.probes_sent = 1; 01742 nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST); 01743 } else { 01744 neighbor_cache[neighbor_index].state = ND6_STALE; 01745 } 01746 } 01747 01748 /* Mark neighbor as router. */ 01749 neighbor_cache[neighbor_index].isrouter = 1; 01750 01751 /* Look for empty entry. */ 01752 free_router_index = LWIP_ND6_NUM_ROUTERS; 01753 for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) { 01754 /* check if router already exists (this is a special case for 2 netifs on the same subnet 01755 - e.g. wifi and cable) */ 01756 if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ 01757 return router_index; 01758 } 01759 if (default_router_list[router_index].neighbor_entry == NULL) { 01760 /* remember lowest free index to create a new entry */ 01761 free_router_index = router_index; 01762 } 01763 } 01764 if (free_router_index < LWIP_ND6_NUM_ROUTERS) { 01765 default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); 01766 return free_router_index; 01767 } 01768 01769 /* Could not create a router entry. */ 01770 01771 /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ 01772 neighbor_cache[neighbor_index].isrouter = 0; 01773 01774 /* router not found. */ 01775 return -1; 01776 } 01777 01778 /** 01779 * Find the cached entry for an on-link prefix. 01780 * 01781 * @param prefix the IPv6 prefix that is on-link 01782 * @param netif the netif on which the prefix is on-link 01783 * @return the index on the prefix table, or -1 if not found 01784 */ 01785 static s8_t 01786 nd6_get_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif) 01787 { 01788 s8_t i; 01789 01790 /* Look for prefix in list. */ 01791 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { 01792 if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && 01793 (prefix_list[i].netif == netif)) { 01794 return i; 01795 } 01796 } 01797 01798 /* Entry not available. */ 01799 return -1; 01800 } 01801 01802 /** 01803 * Creates a new entry for an on-link prefix. 01804 * 01805 * @param prefix the IPv6 prefix that is on-link 01806 * @param netif the netif on which the prefix is on-link 01807 * @return the index on the prefix table, or -1 if not created 01808 */ 01809 static s8_t 01810 nd6_new_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif) 01811 { 01812 s8_t i; 01813 01814 /* Create new entry. */ 01815 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { 01816 if ((prefix_list[i].netif == NULL) || 01817 (prefix_list[i].invalidation_timer == 0)) { 01818 /* Found empty prefix entry. */ 01819 prefix_list[i].netif = netif; 01820 ip6_addr_set(&(prefix_list[i].prefix), prefix); 01821 return i; 01822 } 01823 } 01824 01825 /* Entry not available. */ 01826 return -1; 01827 } 01828 01829 /** 01830 * Determine the next hop for a destination. Will determine if the 01831 * destination is on-link, else a suitable on-link router is selected. 01832 * 01833 * The last entry index is cached for fast entry search. 01834 * 01835 * @param ip6addr the destination address 01836 * @param netif the netif on which the packet will be sent 01837 * @return the neighbor cache entry for the next hop, ERR_RTE if no 01838 * suitable next hop was found, ERR_MEM if no cache entry 01839 * could be created 01840 */ 01841 static s8_t 01842 nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) 01843 { 01844 #ifdef LWIP_HOOK_ND6_GET_GW 01845 const ip6_addr_t *next_hop_addr; 01846 #endif /* LWIP_HOOK_ND6_GET_GW */ 01847 s8_t i; 01848 01849 #if LWIP_NETIF_HWADDRHINT 01850 if (netif->addr_hint != NULL) { 01851 /* per-pcb cached entry was given */ 01852 u8_t addr_hint = *(netif->addr_hint); 01853 if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { 01854 nd6_cached_destination_index = addr_hint; 01855 } 01856 } 01857 #endif /* LWIP_NETIF_HWADDRHINT */ 01858 01859 /* Look for ip6addr in destination cache. */ 01860 if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { 01861 /* the cached entry index is the right one! */ 01862 /* do nothing. */ 01863 ND6_STATS_INC(nd6.cachehit); 01864 } else { 01865 /* Search destination cache. */ 01866 i = nd6_find_destination_cache_entry(ip6addr); 01867 if (i >= 0) { 01868 /* found destination entry. make it our new cached index. */ 01869 nd6_cached_destination_index = i; 01870 } else { 01871 /* Not found. Create a new destination entry. */ 01872 i = nd6_new_destination_cache_entry(); 01873 if (i >= 0) { 01874 /* got new destination entry. make it our new cached index. */ 01875 nd6_cached_destination_index = i; 01876 } else { 01877 /* Could not create a destination cache entry. */ 01878 return ERR_MEM; 01879 } 01880 01881 /* Copy dest address to destination cache. */ 01882 ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); 01883 01884 /* Now find the next hop. is it a neighbor? */ 01885 if (ip6_addr_islinklocal(ip6addr) || 01886 nd6_is_prefix_in_netif(ip6addr, netif)) { 01887 /* Destination in local link. */ 01888 destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; 01889 ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); 01890 #ifdef LWIP_HOOK_ND6_GET_GW 01891 } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { 01892 /* Next hop for destination provided by hook function. */ 01893 destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; 01894 ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr); 01895 #endif /* LWIP_HOOK_ND6_GET_GW */ 01896 } else { 01897 /* We need to select a router. */ 01898 i = nd6_select_router(ip6addr, netif); 01899 if (i < 0) { 01900 /* No router found. */ 01901 ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); 01902 return ERR_RTE; 01903 } 01904 destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ 01905 ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); 01906 } 01907 } 01908 } 01909 01910 #if LWIP_NETIF_HWADDRHINT 01911 if (netif->addr_hint != NULL) { 01912 /* per-pcb cached entry was given */ 01913 *(netif->addr_hint) = nd6_cached_destination_index; 01914 } 01915 #endif /* LWIP_NETIF_HWADDRHINT */ 01916 01917 /* Look in neighbor cache for the next-hop address. */ 01918 if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), 01919 &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { 01920 /* Cache hit. */ 01921 /* Do nothing. */ 01922 ND6_STATS_INC(nd6.cachehit); 01923 } else { 01924 i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); 01925 if (i >= 0) { 01926 /* Found a matching record, make it new cached entry. */ 01927 nd6_cached_neighbor_index = i; 01928 } else { 01929 /* Neighbor not in cache. Make a new entry. */ 01930 i = nd6_new_neighbor_cache_entry(); 01931 if (i >= 0) { 01932 /* got new neighbor entry. make it our new cached index. */ 01933 nd6_cached_neighbor_index = i; 01934 } else { 01935 /* Could not create a neighbor cache entry. */ 01936 return ERR_MEM; 01937 } 01938 01939 /* Initialize fields. */ 01940 ip6_addr_copy(neighbor_cache[i].next_hop_address, 01941 destination_cache[nd6_cached_destination_index].next_hop_addr); 01942 neighbor_cache[i].isrouter = 0; 01943 neighbor_cache[i].netif = netif; 01944 neighbor_cache[i].state = ND6_INCOMPLETE; 01945 neighbor_cache[i].counter.probes_sent = 1; 01946 nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); 01947 } 01948 } 01949 01950 /* Reset this destination's age. */ 01951 destination_cache[nd6_cached_destination_index].age = 0; 01952 01953 return nd6_cached_neighbor_index; 01954 } 01955 01956 /** 01957 * Queue a packet for a neighbor. 01958 * 01959 * @param neighbor_index the index in the neighbor cache table 01960 * @param q packet to be queued 01961 * @return ERR_OK if succeeded, ERR_MEM if out of memory 01962 */ 01963 static err_t 01964 nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) 01965 { 01966 err_t result = ERR_MEM; 01967 struct pbuf *p; 01968 int copy_needed = 0; 01969 #if LWIP_ND6_QUEUEING 01970 struct nd6_q_entry *new_entry, *r; 01971 #endif /* LWIP_ND6_QUEUEING */ 01972 01973 if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { 01974 return ERR_ARG; 01975 } 01976 01977 /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but 01978 * to copy the whole queue into a new PBUF_RAM (see bug #11400) 01979 * PBUF_ROMs can be left as they are, since ROM must not get changed. */ 01980 p = q; 01981 while (p) { 01982 if (p->type != PBUF_ROM) { 01983 copy_needed = 1; 01984 break; 01985 } 01986 p = p->next; 01987 } 01988 if (copy_needed) { 01989 /* copy the whole packet into new pbufs */ 01990 p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); 01991 while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { 01992 /* Free oldest packet (as per RFC recommendation) */ 01993 #if LWIP_ND6_QUEUEING 01994 r = neighbor_cache[neighbor_index].q; 01995 neighbor_cache[neighbor_index].q = r->next; 01996 r->next = NULL; 01997 nd6_free_q(r); 01998 #else /* LWIP_ND6_QUEUEING */ 01999 pbuf_free(neighbor_cache[neighbor_index].q); 02000 neighbor_cache[neighbor_index].q = NULL; 02001 #endif /* LWIP_ND6_QUEUEING */ 02002 p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); 02003 } 02004 if (p != NULL) { 02005 if (pbuf_copy(p, q) != ERR_OK) { 02006 pbuf_free(p); 02007 p = NULL; 02008 } 02009 } 02010 } else { 02011 /* referencing the old pbuf is enough */ 02012 p = q; 02013 pbuf_ref(p); 02014 } 02015 /* packet was copied/ref'd? */ 02016 if (p != NULL) { 02017 /* queue packet ... */ 02018 #if LWIP_ND6_QUEUEING 02019 /* allocate a new nd6 queue entry */ 02020 new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); 02021 if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { 02022 /* Free oldest packet (as per RFC recommendation) */ 02023 r = neighbor_cache[neighbor_index].q; 02024 neighbor_cache[neighbor_index].q = r->next; 02025 r->next = NULL; 02026 nd6_free_q(r); 02027 new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); 02028 } 02029 if (new_entry != NULL) { 02030 new_entry->next = NULL; 02031 new_entry->p = p; 02032 if (neighbor_cache[neighbor_index].q != NULL) { 02033 /* queue was already existent, append the new entry to the end */ 02034 r = neighbor_cache[neighbor_index].q; 02035 while (r->next != NULL) { 02036 r = r->next; 02037 } 02038 r->next = new_entry; 02039 } else { 02040 /* queue did not exist, first item in queue */ 02041 neighbor_cache[neighbor_index].q = new_entry; 02042 } 02043 LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); 02044 result = ERR_OK; 02045 } else { 02046 /* the pool MEMP_ND6_QUEUE is empty */ 02047 pbuf_free(p); 02048 LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); 02049 /* { result == ERR_MEM } through initialization */ 02050 } 02051 #else /* LWIP_ND6_QUEUEING */ 02052 /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ 02053 if (neighbor_cache[neighbor_index].q != NULL) { 02054 pbuf_free(neighbor_cache[neighbor_index].q); 02055 } 02056 neighbor_cache[neighbor_index].q = p; 02057 LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); 02058 result = ERR_OK; 02059 #endif /* LWIP_ND6_QUEUEING */ 02060 } else { 02061 LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); 02062 /* { result == ERR_MEM } through initialization */ 02063 } 02064 02065 return result; 02066 } 02067 02068 #if LWIP_ND6_QUEUEING 02069 /** 02070 * Free a complete queue of nd6 q entries 02071 * 02072 * @param q a queue of nd6_q_entry to free 02073 */ 02074 static void 02075 nd6_free_q(struct nd6_q_entry *q) 02076 { 02077 struct nd6_q_entry *r; 02078 LWIP_ASSERT("q != NULL", q != NULL); 02079 LWIP_ASSERT("q->p != NULL", q->p != NULL); 02080 while (q) { 02081 r = q; 02082 q = q->next; 02083 LWIP_ASSERT("r->p != NULL", (r->p != NULL)); 02084 pbuf_free(r->p); 02085 memp_free(MEMP_ND6_QUEUE, r); 02086 } 02087 } 02088 #endif /* LWIP_ND6_QUEUEING */ 02089 02090 /** 02091 * Send queued packets for a neighbor 02092 * 02093 * @param i the neighbor to send packets to 02094 */ 02095 static void 02096 nd6_send_q(s8_t i) 02097 { 02098 struct ip6_hdr *ip6hdr; 02099 ip6_addr_t dest; 02100 #if LWIP_ND6_QUEUEING 02101 struct nd6_q_entry *q; 02102 #endif /* LWIP_ND6_QUEUEING */ 02103 02104 if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { 02105 return; 02106 } 02107 02108 #if LWIP_ND6_QUEUEING 02109 while (neighbor_cache[i].q != NULL) { 02110 /* remember first in queue */ 02111 q = neighbor_cache[i].q; 02112 /* pop first item off the queue */ 02113 neighbor_cache[i].q = q->next; 02114 /* Get ipv6 header. */ 02115 ip6hdr = (struct ip6_hdr *)(q->p->payload); 02116 /* Create an aligned copy. */ 02117 ip6_addr_set(&dest, &(ip6hdr->dest)); 02118 /* send the queued IPv6 packet */ 02119 (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest); 02120 /* free the queued IP packet */ 02121 pbuf_free(q->p); 02122 /* now queue entry can be freed */ 02123 memp_free(MEMP_ND6_QUEUE, q); 02124 } 02125 #else /* LWIP_ND6_QUEUEING */ 02126 if (neighbor_cache[i].q != NULL) { 02127 /* Get ipv6 header. */ 02128 ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); 02129 /* Create an aligned copy. */ 02130 ip6_addr_set(&dest, &(ip6hdr->dest)); 02131 /* send the queued IPv6 packet */ 02132 (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest); 02133 /* free the queued IP packet */ 02134 pbuf_free(neighbor_cache[i].q); 02135 neighbor_cache[i].q = NULL; 02136 } 02137 #endif /* LWIP_ND6_QUEUEING */ 02138 } 02139 02140 /** 02141 * A packet is to be transmitted to a specific IPv6 destination on a specific 02142 * interface. Check if we can find the hardware address of the next hop to use 02143 * for the packet. If so, give the hardware address to the caller, which should 02144 * use it to send the packet right away. Otherwise, enqueue the packet for 02145 * later transmission while looking up the hardware address, if possible. 02146 * 02147 * As such, this function returns one of three different possible results: 02148 * 02149 * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now. 02150 * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later. 02151 * - not ERR_OK: something went wrong; forward the error upward in the stack. 02152 * 02153 * @param netif The lwIP network interface on which the IP packet will be sent. 02154 * @param q The pbuf(s) containing the IP packet to be sent. 02155 * @param ip6addr The destination IPv6 address of the packet. 02156 * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning 02157 * the packet has been queued). 02158 * @return 02159 * - ERR_OK on success, ERR_RTE if no route was found for the packet, 02160 * or ERR_MEM if low memory conditions prohibit sending the packet at all. 02161 */ 02162 err_t 02163 nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp) 02164 { 02165 s8_t i; 02166 02167 /* Get next hop record. */ 02168 i = nd6_get_next_hop_entry(ip6addr, netif); 02169 if (i < 0) { 02170 /* failed to get a next hop neighbor record. */ 02171 return i; 02172 } 02173 02174 /* Now that we have a destination record, send or queue the packet. */ 02175 if (neighbor_cache[i].state == ND6_STALE) { 02176 /* Switch to delay state. */ 02177 neighbor_cache[i].state = ND6_DELAY; 02178 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; 02179 } 02180 /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ 02181 if ((neighbor_cache[i].state == ND6_REACHABLE) || 02182 (neighbor_cache[i].state == ND6_DELAY) || 02183 (neighbor_cache[i].state == ND6_PROBE)) { 02184 02185 /* Tell the caller to send out the packet now. */ 02186 *hwaddrp = neighbor_cache[i].lladdr; 02187 return ERR_OK; 02188 } 02189 02190 /* We should queue packet on this interface. */ 02191 *hwaddrp = NULL; 02192 return nd6_queue_packet(i, q); 02193 } 02194 02195 02196 /** 02197 * Get the Path MTU for a destination. 02198 * 02199 * @param ip6addr the destination address 02200 * @param netif the netif on which the packet will be sent 02201 * @return the Path MTU, if known, or the netif default MTU 02202 */ 02203 u16_t 02204 nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) 02205 { 02206 s8_t i; 02207 02208 i = nd6_find_destination_cache_entry(ip6addr); 02209 if (i >= 0) { 02210 if (destination_cache[i].pmtu > 0) { 02211 return destination_cache[i].pmtu; 02212 } 02213 } 02214 02215 if (netif != NULL) { 02216 return netif->mtu; 02217 } 02218 02219 return 1280; /* Minimum MTU */ 02220 } 02221 02222 02223 #if LWIP_ND6_TCP_REACHABILITY_HINTS 02224 /** 02225 * Provide the Neighbor discovery process with a hint that a 02226 * destination is reachable. Called by tcp_receive when ACKs are 02227 * received or sent (as per RFC). This is useful to avoid sending 02228 * NS messages every 30 seconds. 02229 * 02230 * @param ip6addr the destination address which is know to be reachable 02231 * by an upper layer protocol (TCP) 02232 */ 02233 void 02234 nd6_reachability_hint(const ip6_addr_t *ip6addr) 02235 { 02236 s8_t i; 02237 02238 /* Find destination in cache. */ 02239 if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { 02240 i = nd6_cached_destination_index; 02241 ND6_STATS_INC(nd6.cachehit); 02242 } else { 02243 i = nd6_find_destination_cache_entry(ip6addr); 02244 } 02245 if (i < 0) { 02246 return; 02247 } 02248 02249 /* Find next hop neighbor in cache. */ 02250 if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { 02251 i = nd6_cached_neighbor_index; 02252 ND6_STATS_INC(nd6.cachehit); 02253 } else { 02254 i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); 02255 } 02256 if (i < 0) { 02257 return; 02258 } 02259 02260 /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */ 02261 if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) { 02262 return; 02263 } 02264 02265 /* Set reachability state. */ 02266 neighbor_cache[i].state = ND6_REACHABLE; 02267 neighbor_cache[i].counter.reachable_time = reachable_time; 02268 } 02269 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ 02270 02271 /** 02272 * Remove all prefix, neighbor_cache and router entries of the specified netif. 02273 * 02274 * @param netif points to a network interface 02275 */ 02276 void 02277 nd6_cleanup_netif(struct netif *netif) 02278 { 02279 u8_t i; 02280 s8_t router_index; 02281 for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { 02282 if (prefix_list[i].netif == netif) { 02283 prefix_list[i].netif = NULL; 02284 } 02285 } 02286 for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { 02287 if (neighbor_cache[i].netif == netif) { 02288 for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { 02289 if (default_router_list[router_index].neighbor_entry == &neighbor_cache[i]) { 02290 default_router_list[router_index].neighbor_entry = NULL; 02291 default_router_list[router_index].flags = 0; 02292 } 02293 } 02294 neighbor_cache[i].isrouter = 0; 02295 nd6_free_neighbor_cache_entry(i); 02296 } 02297 } 02298 /* Clear the destination cache, since many entries may now have become 02299 * invalid for one of several reasons. As destination cache entries have no 02300 * netif association, use a sledgehammer approach (this can be improved). */ 02301 nd6_clear_destination_cache(); 02302 } 02303 02304 #if LWIP_IPV6_MLD 02305 /** 02306 * The state of a local IPv6 address entry is about to change. If needed, join 02307 * or leave the solicited-node multicast group for the address. 02308 * 02309 * @param netif The netif that owns the address. 02310 * @param addr_idx The index of the address. 02311 * @param new_state The new (IP6_ADDR_) state for the address. 02312 */ 02313 void 02314 nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state) 02315 { 02316 u8_t old_state, old_member, new_member; 02317 02318 old_state = netif_ip6_addr_state(netif, addr_idx); 02319 02320 /* Determine whether we were, and should be, a member of the solicited-node 02321 * multicast group for this address. For tentative addresses, the group is 02322 * not joined until the address enters the TENTATIVE_1 (or VALID) state. */ 02323 old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_DUPLICATED && old_state != IP6_ADDR_TENTATIVE); 02324 new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_DUPLICATED && new_state != IP6_ADDR_TENTATIVE); 02325 02326 if (old_member != new_member) { 02327 ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]); 02328 02329 if (new_member) { 02330 mld6_joingroup_netif(netif, &multicast_address); 02331 } else { 02332 mld6_leavegroup_netif(netif, &multicast_address); 02333 } 02334 } 02335 } 02336 #endif /* LWIP_IPV6_MLD */ 02337 02338 #endif /* LWIP_IPV6 */
Generated on Sun Jul 17 2022 08:25:24 by 1.7.2