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