Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / lwip / repo / lwip / src / core / ipv6 / nd6.c
1 /**
2  * @file
3  *
4  * Neighbor discovery and stateless address autoconfiguration for IPv6.
5  * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
6  * (Address autoconfiguration).
7  */
8
9 /*
10  * Copyright (c) 2010 Inico Technologies Ltd.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,
14  * are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  *    this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33  * OF SUCH DAMAGE.
34  *
35  * This file is part of the lwIP TCP/IP stack.
36  *
37  * Author: Ivan Delamer <delamer@inicotech.com>
38  *
39  *
40  * Please coordinate changes and requests with Ivan Delamer
41  * <delamer@inicotech.com>
42  */
43
44 #include "lwip/opt.h"
45
46 /* don't build if not configured for use in lwipopts.h */
47 #if LWIP_IPV6 && LWIP_IPV6_ND
48
49 #include "lwip/nd6.h"
50 #include "lwip/priv/nd6_priv.h"
51 #include "lwip/prot/nd6.h"
52 #include "lwip/prot/icmp6.h"
53 #include "lwip/pbuf.h"
54 #include "lwip/mem.h"
55 #include "lwip/memp.h"
56 #include "lwip/ip6.h"
57 #include "lwip/ip6_addr.h"
58 #include "lwip/inet_chksum.h"
59 #include "lwip/netif.h"
60 #include "lwip/icmp6.h"
61 #include "lwip/mld6.h"
62 #include "lwip/ip.h"
63 #include "lwip/stats.h"
64 #include "lwip/dns.h"
65
66 #include <string.h>
67
68 #ifdef LWIP_HOOK_FILENAME
69 #include LWIP_HOOK_FILENAME
70 #endif
71
72 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
73 #error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
74 #endif
75
76 /* Router tables. */
77 struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS];
78 struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS];
79 #if LWIP_ND6_LISTEN_RA
80 struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES];
81 #endif
82 #if LWIP_IPV6_ROUTER_SUPPORT
83 struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS];
84 #endif /* LWIP_IPV6_ROUTER_SUPPORT */
85
86 /* Default values, can be updated by a RA message. */
87 u32_t reachable_time = LWIP_ND6_REACHABLE_TIME;
88 u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */
89
90 /* Index for cache entries. */
91 static u8_t nd6_cached_neighbor_index;
92 static u8_t nd6_cached_destination_index;
93
94 /* Multicast address holder. */
95 static ip6_addr_t multicast_address;
96
97 /* Static buffer to parse RA packet options (size of a prefix option, biggest option) */
98 #if LWIP_IPV6_ROUTER_SUPPORT && LWIP_ND6_LISTEN_RA
99 static u8_t nd6_ra_buffer[sizeof(struct prefix_option)];
100 #endif
101
102 /* Forward declarations. */
103 static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr);
104 static s8_t nd6_new_neighbor_cache_entry(void);
105 static void nd6_free_neighbor_cache_entry(s8_t i);
106 static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
107 static s8_t nd6_new_destination_cache_entry(void);
108 static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif);
109 #if LWIP_IPV6_ROUTER_SUPPORT
110 static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
111 #endif /* LWIP_IPV6_ROUTER_SUPPORT */
112 #if LWIP_ND6_LISTEN_RA
113 static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif);
114 static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif);
115 static s8_t nd6_get_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif);
116 static s8_t nd6_new_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif);
117 #endif /* LWIP_ND6_LISTEN_RA */
118 static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif);
119 static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q);
120
121 #define ND6_SEND_FLAG_MULTICAST_DEST 0x01
122 #define ND6_SEND_FLAG_ALLNODES_DEST 0x02
123 #define ND6_SEND_FLAG_ANY_SRC 0x04
124 static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags);
125 static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags);
126 static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags);
127 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
128 static err_t nd6_send_rs(struct netif *netif);
129 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
130
131 #if LWIP_ND6_QUEUEING
132 static void nd6_free_q(struct nd6_q_entry *q);
133 #else /* LWIP_ND6_QUEUEING */
134 #define nd6_free_q(q) pbuf_free(q)
135 #endif /* LWIP_ND6_QUEUEING */
136 static void nd6_send_q(s8_t i);
137
138
139 /**
140  * A local address has been determined to be a duplicate. Take the appropriate
141  * action(s) on the address and the interface as a whole.
142  *
143  * @param netif the netif that owns the address
144  * @param addr_idx the index of the address detected to be a duplicate
145  */
146 static void
147 nd6_duplicate_addr_detected(struct netif *netif, s8_t addr_idx)
148 {
149
150   /* Mark the address as duplicate, but leave its lifetimes alone. If this was
151    * a manually assigned address, it will remain in existence as duplicate, and
152    * as such be unusable for any practical purposes until manual intervention.
153    * If this was an autogenerated address, the address will follow normal
154    * expiration rules, and thus disappear once its valid lifetime expires. */
155   netif_ip6_addr_set_state(netif, addr_idx, IP6_ADDR_DUPLICATED);
156
157 #if LWIP_IPV6_AUTOCONFIG
158   /* If the affected address was the link-local address that we use to generate
159    * all other addresses, then we should not continue to use those derived
160    * addresses either, so mark them as duplicate as well. For autoconfig-only
161    * setups, this will make the interface effectively unusable, approaching the
162    * intention of RFC 4862 Sec. 5.4.5. @todo implement the full requirements */
163   if (addr_idx == 0) {
164     s8_t i;
165     for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
166       if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
167           !netif_ip6_addr_isstatic(netif, i)) {
168         netif_ip6_addr_set_state(netif, i, IP6_ADDR_DUPLICATED);
169       }
170     }
171   }
172 #endif /* LWIP_IPV6_AUTOCONFIG */
173 }
174
175 #if LWIP_IPV6_AUTOCONFIG
176 /**
177  * We received a router advertisement that contains a prefix with the
178  * autoconfiguration flag set. Add or update an associated autogenerated
179  * address.
180  *
181  * @param netif the netif on which the router advertisement arrived
182  * @param prefix_opt a pointer to the prefix option data
183  * @param prefix_addr an aligned copy of the prefix address
184  */
185 static void
186 nd6_process_autoconfig_prefix(struct netif *netif,
187   struct prefix_option *prefix_opt, const ip6_addr_t *prefix_addr)
188 {
189   ip6_addr_t ip6addr;
190   u32_t valid_life, pref_life;
191   u8_t addr_state;
192   s8_t i, free_idx;
193
194   /* The caller already checks RFC 4862 Sec. 5.5.3 points (a) and (b). We do
195    * the rest, starting with checks for (c) and (d) here. */
196   valid_life = lwip_htonl(prefix_opt->valid_lifetime);
197   pref_life = lwip_htonl(prefix_opt->preferred_lifetime);
198   if (pref_life > valid_life || prefix_opt->prefix_length != 64) {
199     return; /* silently ignore this prefix for autoconfiguration purposes */
200   }
201
202   /* If an autogenerated address already exists for this prefix, update its
203    * lifetimes. An address is considered autogenerated if 1) it is not static
204    * (i.e., manually assigned), and 2) there is an advertised autoconfiguration
205    * prefix for it (the one we are processing here). This does not necessarily
206    * exclude the possibility that the address was actually assigned by, say,
207    * DHCPv6. If that distinction becomes important in the future, more state
208    * must be kept. As explained elsewhere we also update lifetimes of tentative
209    * and duplicate addresses. Skip address slot 0 (the link-local address). */
210   for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
211     addr_state = netif_ip6_addr_state(netif, i);
212     if (!ip6_addr_isinvalid(addr_state) && !netif_ip6_addr_isstatic(netif, i) &&
213         ip6_addr_netcmp(prefix_addr, netif_ip6_addr(netif, i))) {
214       /* Update the valid lifetime, as per RFC 4862 Sec. 5.5.3 point (e).
215        * The valid lifetime will never drop to zero as a result of this. */
216       u32_t remaining_life = netif_ip6_addr_valid_life(netif, i);
217       if (valid_life > ND6_2HRS || valid_life > remaining_life) {
218         netif_ip6_addr_set_valid_life(netif, i, valid_life);
219       } else if (remaining_life > ND6_2HRS) {
220         netif_ip6_addr_set_valid_life(netif, i, ND6_2HRS);
221       }
222       LWIP_ASSERT("bad valid lifetime", !netif_ip6_addr_isstatic(netif, i));
223       /* Update the preferred lifetime. No bounds checks are needed here. In
224        * rare cases the advertisement may un-deprecate the address, though.
225        * Deprecation is left to the timer code where it is handled anyway. */
226       if (pref_life > 0 && addr_state == IP6_ADDR_DEPRECATED) {
227         netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
228       }
229       netif_ip6_addr_set_pref_life(netif, i, pref_life);
230       return; /* there should be at most one matching address */
231     }
232   }
233
234   /* No autogenerated address exists for this prefix yet. See if we can add a
235    * new one. However, if IPv6 autoconfiguration is administratively disabled,
236    * do not generate new addresses, but do keep updating lifetimes for existing
237    * addresses. Also, when adding new addresses, we must protect explicitly
238    * against a valid lifetime of zero, because again, we use that as a special
239    * value. The generated address would otherwise expire immediately anyway.
240    * Finally, the original link-local address must be usable at all. We start
241    * creating addresses even if the link-local address is still in tentative
242    * state though, and deal with the fallout of that upon DAD collision. */
243   addr_state = netif_ip6_addr_state(netif, 0);
244   if (!netif->ip6_autoconfig_enabled || valid_life == IP6_ADDR_LIFE_STATIC ||
245       ip6_addr_isinvalid(addr_state) || ip6_addr_isduplicated(addr_state)) {
246     return;
247   }
248
249   /* Construct the new address that we intend to use, and then see if that
250    * address really does not exist. It might have been added manually, after
251    * all. As a side effect, find a free slot. Note that we cannot use
252    * netif_add_ip6_address() here, as it would return ERR_OK if the address
253    * already did exist, resulting in that address being given lifetimes. */
254   IP6_ADDR(&ip6addr, prefix_addr->addr[0], prefix_addr->addr[1],
255     netif_ip6_addr(netif, 0)->addr[2], netif_ip6_addr(netif, 0)->addr[3]);
256
257   free_idx = 0;
258   for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
259     if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
260       if (ip6_addr_cmp(&ip6addr, netif_ip6_addr(netif, i))) {
261         return; /* formed address already exists */
262       }
263     } else if (free_idx == 0) {
264       free_idx = i;
265     }
266   }
267   if (free_idx == 0) {
268     return; /* no address slots available, try again on next advertisement */
269   }
270
271   /* Assign the new address to the interface. */
272   ip_addr_copy_from_ip6(netif->ip6_addr[free_idx], ip6addr);
273   netif_ip6_addr_set_valid_life(netif, free_idx, valid_life);
274   netif_ip6_addr_set_pref_life(netif, free_idx, pref_life);
275   netif_ip6_addr_set_state(netif, free_idx, IP6_ADDR_TENTATIVE);
276 }
277 #endif /* LWIP_IPV6_AUTOCONFIG */
278
279 /**
280  * Process an incoming neighbor discovery message
281  *
282  * @param p the nd packet, p->payload pointing to the icmpv6 header
283  * @param inp the netif on which this packet was received
284  */
285 void
286 nd6_input(struct pbuf *p, struct netif *inp)
287 {
288   u8_t msg_type;
289   s8_t i;
290
291   ND6_STATS_INC(nd6.recv);
292
293   msg_type = *((u8_t *)p->payload);
294   switch (msg_type) {
295   case ICMP6_TYPE_NA: /* Neighbor Advertisement. */
296   {
297     struct na_header *na_hdr;
298     struct lladdr_option *lladdr_opt;
299
300     /* Check that na header fits in packet. */
301     if (p->len < (sizeof(struct na_header))) {
302       /* @todo debug message */
303       pbuf_free(p);
304       ND6_STATS_INC(nd6.lenerr);
305       ND6_STATS_INC(nd6.drop);
306       return;
307     }
308
309     na_hdr = (struct na_header *)p->payload;
310
311     /* Unsolicited NA?*/
312     if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
313       ip6_addr_t target_address;
314       
315       /* This is an unsolicited NA.
316        * link-layer changed?
317        * part of DAD mechanism? */
318
319       /* Check that link-layer address option also fits in packet. */
320       if (p->len < (sizeof(struct na_header) + ND6_LLADDR_OPTION_SIZE(inp->hwaddr_len))) {
321         /* TODO debug message */
322         pbuf_free(p);
323         ND6_STATS_INC(nd6.lenerr);
324         ND6_STATS_INC(nd6.drop);
325         return;
326       }
327
328       lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
329
330       /* Override ip6_current_dest_addr() so that we have an aligned copy. */
331       ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address));
332
333 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
334       /* If the target address matches this netif, it is a DAD response. */
335       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
336         if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
337             !ip6_addr_isduplicated(netif_ip6_addr_state(inp, i)) &&
338             ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) {
339           /* We are using a duplicate address. */
340           nd6_duplicate_addr_detected(inp, i);
341
342           pbuf_free(p);
343           return;
344         }
345       }
346 #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
347
348       /* Check that link-layer address option also fits in packet. */
349       if (p->len < (sizeof(struct na_header) + 2)) {
350         /* @todo debug message */
351         pbuf_free(p);
352         ND6_STATS_INC(nd6.lenerr);
353         ND6_STATS_INC(nd6.drop);
354         return;
355       }
356
357       lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
358
359       if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) {
360         /* @todo debug message */
361         pbuf_free(p);
362         ND6_STATS_INC(nd6.lenerr);
363         ND6_STATS_INC(nd6.drop);
364         return;
365       }
366
367       /* This is an unsolicited NA, most likely there was a LLADDR change. */
368       i = nd6_find_neighbor_cache_entry(&target_address);
369       if (i >= 0) {
370         if (na_hdr->flags & ND6_FLAG_OVERRIDE) {
371           MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
372         }
373       }
374     } else {
375       ip6_addr_t target_address;
376
377       /* This is a solicited NA.
378        * neighbor address resolution response?
379        * neighbor unreachability detection response? */
380
381       /* Create an aligned copy. */
382       ip6_addr_set(&target_address, &(na_hdr->target_address));
383
384       /* Find the cache entry corresponding to this na. */
385       i = nd6_find_neighbor_cache_entry(&target_address);
386       if (i < 0) {
387         /* We no longer care about this target address. drop it. */
388         pbuf_free(p);
389         return;
390       }
391
392       /* Update cache entry. */
393       if ((na_hdr->flags & ND6_FLAG_OVERRIDE) ||
394           (neighbor_cache[i].state == ND6_INCOMPLETE)) {
395         /* Check that link-layer address option also fits in packet. */
396         if (p->len < (sizeof(struct na_header) + ND6_LLADDR_OPTION_SIZE(inp->hwaddr_len))) {
397           /* @todo debug message */
398           pbuf_free(p);
399           ND6_STATS_INC(nd6.lenerr);
400           ND6_STATS_INC(nd6.drop);
401           return;
402         }
403
404         lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
405
406         if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) {
407           /* @todo debug message */
408           pbuf_free(p);
409           ND6_STATS_INC(nd6.lenerr);
410           ND6_STATS_INC(nd6.drop);
411           return;
412         }
413
414         MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
415       }
416
417       neighbor_cache[i].netif = inp;
418       neighbor_cache[i].state = ND6_REACHABLE;
419       neighbor_cache[i].counter.reachable_time = reachable_time;
420
421       /* Send queued packets, if any. */
422       if (neighbor_cache[i].q != NULL) {
423         nd6_send_q(i);
424       }
425     }
426
427     break; /* ICMP6_TYPE_NA */
428   }
429   case ICMP6_TYPE_NS: /* Neighbor solicitation. */
430   {
431     struct ns_header *ns_hdr;
432     struct lladdr_option *lladdr_opt;
433     u8_t accepted;
434
435     /* Check that ns header fits in packet. */
436     if (p->len < sizeof(struct ns_header)) {
437       /* @todo debug message */
438       pbuf_free(p);
439       ND6_STATS_INC(nd6.lenerr);
440       ND6_STATS_INC(nd6.drop);
441       return;
442     }
443
444     ns_hdr = (struct ns_header *)p->payload;
445
446     /* Check if there is a link-layer address provided. Only point to it if in this buffer. */
447     lladdr_opt = NULL;
448     if (p->len >= (sizeof(struct ns_header) + ND6_LLADDR_OPTION_SIZE(inp->hwaddr_len))) {
449       lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header));
450       if (p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) {
451         lladdr_opt = NULL;
452       }
453     } else {
454       lladdr_opt = NULL;
455     }
456
457     /* Check if the target address is configured on the receiving netif. */
458     accepted = 0;
459     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
460       if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) ||
461            (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) &&
462             ip6_addr_isany(ip6_current_src_addr()))) &&
463           ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) {
464         accepted = 1;
465         break;
466       }
467     }
468
469     /* NS not for us? */
470     if (!accepted) {
471       pbuf_free(p);
472       return;
473     }
474
475     /* Check for ANY address in src (DAD algorithm). */
476     if (ip6_addr_isany(ip6_current_src_addr())) {
477       /* Sender is validating this address. */
478       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
479         if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
480             ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) {
481           /* Send a NA back so that the sender does not use this address. */
482           nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST);
483           if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) {
484             /* We shouldn't use this address either. */
485             nd6_duplicate_addr_detected(inp, i);
486           }
487         }
488       }
489     } else {
490       ip6_addr_t target_address;
491       
492       /* Sender is trying to resolve our address. */
493       /* Verify that they included their own link-layer address. */
494       if (lladdr_opt == NULL) {
495         /* Not a valid message. */
496         pbuf_free(p);
497         ND6_STATS_INC(nd6.proterr);
498         ND6_STATS_INC(nd6.drop);
499         return;
500       }
501
502       i = nd6_find_neighbor_cache_entry(ip6_current_src_addr());
503       if (i>= 0) {
504         /* We already have a record for the solicitor. */
505         if (neighbor_cache[i].state == ND6_INCOMPLETE) {
506           neighbor_cache[i].netif = inp;
507           MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
508
509           /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
510           neighbor_cache[i].state = ND6_DELAY;
511           neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
512         }
513       } else {
514         /* Add their IPv6 address and link-layer address to neighbor cache.
515          * We will need it at least to send a unicast NA message, but most
516          * likely we will also be communicating with this node soon. */
517         i = nd6_new_neighbor_cache_entry();
518         if (i < 0) {
519           /* We couldn't assign a cache entry for this neighbor.
520            * we won't be able to reply. drop it. */
521           pbuf_free(p);
522           ND6_STATS_INC(nd6.memerr);
523           return;
524         }
525         neighbor_cache[i].netif = inp;
526         MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
527         ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr());
528
529         /* Receiving a message does not prove reachability: only in one direction.
530          * Delay probe in case we get confirmation of reachability from upper layer (TCP). */
531         neighbor_cache[i].state = ND6_DELAY;
532         neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
533       }
534
535       /* Create an aligned copy. */
536       ip6_addr_set(&target_address, &(ns_hdr->target_address));
537
538       /* Send back a NA for us. Allocate the reply pbuf. */
539       nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE);
540     }
541
542     break; /* ICMP6_TYPE_NS */
543   }
544 #if LWIP_IPV6_ROUTER_SUPPORT && LWIP_ND6_LISTEN_RA
545   case ICMP6_TYPE_RA: /* Router Advertisement. */
546   {
547     struct ra_header *ra_hdr;
548     u8_t *buffer; /* Used to copy options. */
549     u16_t offset;
550 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
551     /* There can by multiple RDNSS options per RA */
552     u8_t rdnss_server_idx = 0;
553 #endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
554
555     /* Check that RA header fits in packet. */
556     if (p->len < sizeof(struct ra_header)) {
557       /* @todo debug message */
558       pbuf_free(p);
559       ND6_STATS_INC(nd6.lenerr);
560       ND6_STATS_INC(nd6.drop);
561       return;
562     }
563
564     ra_hdr = (struct ra_header *)p->payload;
565
566     /* If we are sending RS messages, stop. */
567 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
568     /* ensure at least one solicitation is sent */
569     if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) ||
570         (nd6_send_rs(inp) == ERR_OK)) {
571       inp->rs_count = 0;
572     }
573 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
574
575     /* Get the matching default router entry. */
576     i = nd6_get_router(ip6_current_src_addr(), inp);
577     if (i < 0) {
578       /* Create a new router entry. */
579       i = nd6_new_router(ip6_current_src_addr(), inp);
580     }
581
582     if (i < 0) {
583       /* Could not create a new router entry. */
584       pbuf_free(p);
585       ND6_STATS_INC(nd6.memerr);
586       return;
587     }
588
589     /* Re-set invalidation timer. */
590     default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime);
591
592     /* Re-set default timer values. */
593 #if LWIP_ND6_ALLOW_RA_UPDATES
594     if (ra_hdr->retrans_timer > 0) {
595       retrans_timer = lwip_htonl(ra_hdr->retrans_timer);
596     }
597     if (ra_hdr->reachable_time > 0) {
598       reachable_time = lwip_htonl(ra_hdr->reachable_time);
599     }
600 #endif /* LWIP_ND6_ALLOW_RA_UPDATES */
601
602     /* @todo set default hop limit... */
603     /* ra_hdr->current_hop_limit;*/
604
605     /* Update flags in local entry (incl. preference). */
606     default_router_list[i].flags = ra_hdr->flags;
607
608     /* Offset to options. */
609     offset = sizeof(struct ra_header);
610
611     /* Process each option. */
612     while ((p->tot_len - offset) > 0) {
613       if (p->len == p->tot_len) {
614         /* no need to copy from contiguous pbuf */
615         buffer = &((u8_t*)p->payload)[offset];
616       } else {
617         buffer = nd6_ra_buffer;
618         if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) {
619           pbuf_free(p);
620           ND6_STATS_INC(nd6.lenerr);
621           ND6_STATS_INC(nd6.drop);
622           return;
623         }
624       }
625       if (buffer[1] == 0) {
626         /* zero-length extension. drop packet */
627         pbuf_free(p);
628         ND6_STATS_INC(nd6.lenerr);
629         ND6_STATS_INC(nd6.drop);
630         return;
631       }
632       switch (buffer[0]) {
633       case ND6_OPTION_TYPE_SOURCE_LLADDR:
634       {
635         struct lladdr_option *lladdr_opt;
636         lladdr_opt = (struct lladdr_option *)buffer;
637         if ((default_router_list[i].neighbor_entry != NULL) &&
638             (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) {
639           SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len);
640           default_router_list[i].neighbor_entry->state = ND6_REACHABLE;
641           default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time;
642         }
643         break;
644       }
645       case ND6_OPTION_TYPE_MTU:
646       {
647         struct mtu_option *mtu_opt;
648         mtu_opt = (struct mtu_option *)buffer;
649         if (lwip_htonl(mtu_opt->mtu) >= IP6_MIN_MTU) {
650 #if LWIP_ND6_ALLOW_RA_UPDATES
651           inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu);
652 #endif /* LWIP_ND6_ALLOW_RA_UPDATES */
653         }
654         break;
655       }
656       case ND6_OPTION_TYPE_PREFIX_INFO:
657       {
658         struct prefix_option *prefix_opt;
659         ip6_addr_t prefix_addr;
660
661         prefix_opt = (struct prefix_option *)buffer;
662
663         /* Get a memory-aligned copy of the prefix. */
664         ip6_addr_set(&prefix_addr, &(prefix_opt->prefix));
665
666         if (!ip6_addr_islinklocal(&prefix_addr)) {
667           if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) &&
668               (prefix_opt->prefix_length == 64)) {
669             /* Add to on-link prefix list. */
670             u32_t valid_life;
671             s8_t prefix;
672
673             valid_life = lwip_htonl(prefix_opt->valid_lifetime);
674
675             /* find cache entry for this prefix. */
676             prefix = nd6_get_onlink_prefix(&prefix_addr, inp);
677             if (prefix < 0 && valid_life > 0) {
678               /* Create a new cache entry. */
679               prefix = nd6_new_onlink_prefix(&prefix_addr, inp);
680             }
681             if (prefix >= 0) {
682               prefix_list[prefix].invalidation_timer = valid_life;
683             }
684           }
685 #if LWIP_IPV6_AUTOCONFIG
686           if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) {
687             /* Perform processing for autoconfiguration. */
688             nd6_process_autoconfig_prefix(inp, prefix_opt, &prefix_addr);
689           }
690 #endif /* LWIP_IPV6_AUTOCONFIG */
691         }
692
693         break;
694       }
695       case ND6_OPTION_TYPE_ROUTE_INFO:
696         /* @todo implement preferred routes.
697         struct route_option * route_opt;
698         route_opt = (struct route_option *)buffer;*/
699
700         break;
701 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
702       case ND6_OPTION_TYPE_RDNSS:
703       {
704         u8_t num, n;
705         struct rdnss_option * rdnss_opt;
706
707         rdnss_opt = (struct rdnss_option *)buffer;
708         num = (rdnss_opt->length - 1) / 2;
709         for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) {
710           ip_addr_t rdnss_address;
711
712           /* Get a memory-aligned copy of the prefix. */
713           ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]);
714
715           if (htonl(rdnss_opt->lifetime) > 0) {
716             /* TODO implement Lifetime > 0 */
717             dns_setserver(rdnss_server_idx++, &rdnss_address);
718           } else {
719             /* TODO implement DNS removal in dns.c */
720             u8_t s;
721             for (s = 0; s < DNS_MAX_SERVERS; s++) {
722               const ip_addr_t *addr = dns_getserver(s);
723               if(ip_addr_cmp(addr, &rdnss_address)) {
724                 dns_setserver(s, NULL);
725               }
726             }
727           }
728         }
729         break;
730       }
731 #endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
732       default:
733         /* Unrecognized option, abort. */
734         ND6_STATS_INC(nd6.proterr);
735         break;
736       }
737       /* option length is checked earlier to be non-zero to make sure loop ends */
738       offset += 8 * ((u16_t)buffer[1]);
739     }
740
741     break; /* ICMP6_TYPE_RA */
742   }
743 #endif /* LWIP_IPV6_ROUTER_SUPPORT && LWIP_ND6_LISTEN_RA */
744   case ICMP6_TYPE_RD: /* Redirect */
745   {
746     struct redirect_header *redir_hdr;
747     struct lladdr_option *lladdr_opt;
748     ip6_addr_t tmp;
749
750     /* Check that Redir header fits in packet. */
751     if (p->len < sizeof(struct redirect_header)) {
752       /* @todo debug message */
753       pbuf_free(p);
754       ND6_STATS_INC(nd6.lenerr);
755       ND6_STATS_INC(nd6.drop);
756       return;
757     }
758
759     redir_hdr = (struct redirect_header *)p->payload;
760
761     lladdr_opt = NULL;
762     if (p->len >= (sizeof(struct redirect_header) + ND6_LLADDR_OPTION_SIZE(inp->hwaddr_len))) {
763       lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header));
764       if (p->len < (sizeof(struct redirect_header) + (lladdr_opt->length << 3))) {
765         lladdr_opt = NULL;
766       }
767     } else {
768       lladdr_opt = NULL;
769     }
770
771     /* Copy original destination address to current source address, to have an aligned copy. */
772     ip6_addr_set(&tmp, &(redir_hdr->destination_address));
773
774     /* Find dest address in cache */
775     i = nd6_find_destination_cache_entry(&tmp);
776     if (i < 0) {
777       /* Destination not in cache, drop packet. */
778       pbuf_free(p);
779       return;
780     }
781
782     /* Set the new target address. */
783     ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address));
784
785     /* If Link-layer address of other router is given, try to add to neighbor cache. */
786     if (lladdr_opt != NULL) {
787       if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) {
788         /* Copy target address to current source address, to have an aligned copy. */
789         ip6_addr_set(&tmp, &(redir_hdr->target_address));
790
791         i = nd6_find_neighbor_cache_entry(&tmp);
792         if (i < 0) {
793           i = nd6_new_neighbor_cache_entry();
794           if (i >= 0) {
795             neighbor_cache[i].netif = inp;
796             MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
797             ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp);
798
799             /* Receiving a message does not prove reachability: only in one direction.
800              * Delay probe in case we get confirmation of reachability from upper layer (TCP). */
801             neighbor_cache[i].state = ND6_DELAY;
802             neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
803           }
804         }
805         if (i >= 0) {
806           if (neighbor_cache[i].state == ND6_INCOMPLETE) {
807             MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
808             /* Receiving a message does not prove reachability: only in one direction.
809              * Delay probe in case we get confirmation of reachability from upper layer (TCP). */
810             neighbor_cache[i].state = ND6_DELAY;
811             neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
812           }
813         }
814       }
815     }
816     break; /* ICMP6_TYPE_RD */
817   }
818   case ICMP6_TYPE_PTB: /* Packet too big */
819   {
820     struct icmp6_hdr *icmp6hdr; /* Packet too big message */
821     struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */
822     u32_t pmtu;
823     ip6_addr_t tmp;
824
825     /* Check that ICMPv6 header + IPv6 header fit in payload */
826     if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) {
827       /* drop short packets */
828       pbuf_free(p);
829       ND6_STATS_INC(nd6.lenerr);
830       ND6_STATS_INC(nd6.drop);
831       return;
832     }
833
834     icmp6hdr = (struct icmp6_hdr *)p->payload;
835     ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr));
836
837     /* Copy original destination address to current source address, to have an aligned copy. */
838     ip6_addr_set(&tmp, &(ip6hdr->dest));
839
840     /* Look for entry in destination cache. */
841     i = nd6_find_destination_cache_entry(&tmp);
842     if (i < 0) {
843       /* Destination not in cache, drop packet. */
844       pbuf_free(p);
845       return;
846     }
847
848     /* Change the Path MTU. */
849     pmtu = lwip_htonl(icmp6hdr->data);
850     destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF);
851
852     break; /* ICMP6_TYPE_PTB */
853   }
854
855   default:
856     ND6_STATS_INC(nd6.proterr);
857     ND6_STATS_INC(nd6.drop);
858     break; /* default */
859   }
860
861   pbuf_free(p);
862 }
863
864
865 /**
866  * Periodic timer for Neighbor discovery functions:
867  *
868  * - Update neighbor reachability states
869  * - Update destination cache entries age
870  * - Update invalidation timers of default routers and on-link prefixes
871  * - Update lifetimes of our addresses
872  * - Perform duplicate address detection (DAD) for our addresses
873  * - Send router solicitations
874  */
875 void
876 nd6_tmr(void)
877 {
878   s8_t i;
879   struct netif *netif;
880
881   /* Process neighbor entries. */
882   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
883     switch (neighbor_cache[i].state) {
884     case ND6_INCOMPLETE:
885       if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) &&
886           (!neighbor_cache[i].isrouter)) {
887         /* Retries exceeded. */
888         nd6_free_neighbor_cache_entry(i);
889       } else {
890         /* Send a NS for this entry. */
891         neighbor_cache[i].counter.probes_sent++;
892         nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST);
893       }
894       break;
895     case ND6_REACHABLE:
896       /* Send queued packets, if any are left. Should have been sent already. */
897       if (neighbor_cache[i].q != NULL) {
898         nd6_send_q(i);
899       }
900       if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) {
901         /* Change to stale state. */
902         neighbor_cache[i].state = ND6_STALE;
903         neighbor_cache[i].counter.stale_time = 0;
904       } else {
905         neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL;
906       }
907       break;
908     case ND6_STALE:
909       neighbor_cache[i].counter.stale_time++;
910       break;
911     case ND6_DELAY:
912       if (neighbor_cache[i].counter.delay_time <= 1) {
913         /* Change to PROBE state. */
914         neighbor_cache[i].state = ND6_PROBE;
915         neighbor_cache[i].counter.probes_sent = 0;
916       } else {
917         neighbor_cache[i].counter.delay_time--;
918       }
919       break;
920     case ND6_PROBE:
921       if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) &&
922           (!neighbor_cache[i].isrouter)) {
923         /* Retries exceeded. */
924         nd6_free_neighbor_cache_entry(i);
925       } else {
926         /* Send a NS for this entry. */
927         neighbor_cache[i].counter.probes_sent++;
928         nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0);
929       }
930       break;
931     case ND6_NO_ENTRY:
932     default:
933       /* Do nothing. */
934       break;
935     }
936   }
937
938   /* Process destination entries. */
939   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
940     destination_cache[i].age++;
941   }
942
943 #if LWIP_IPV6_ROUTER_SUPPORT
944
945   /* Process router entries. */
946   for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) {
947     if (default_router_list[i].neighbor_entry != NULL) {
948       /* Active entry. */
949       if (default_router_list[i].invalidation_timer > 0) {
950         default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
951       }
952       if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) {
953         /* Less than 1 second remaining. Clear this entry. */
954         default_router_list[i].neighbor_entry->isrouter = 0;
955         default_router_list[i].neighbor_entry = NULL;
956         default_router_list[i].invalidation_timer = 0;
957         default_router_list[i].flags = 0;
958       }
959     }
960   }
961
962 #endif /* LWIP_IPV6_ROUTER_SUPPORT */
963
964 #if LWIP_ND6_LISTEN_RA
965
966   /* Process prefix entries. */
967   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
968     if (prefix_list[i].netif != NULL) {
969       if (prefix_list[i].invalidation_timer <= ND6_TMR_INTERVAL / 1000) {
970         /* Entry timed out, remove it */
971         prefix_list[i].invalidation_timer = 0;
972         prefix_list[i].netif = NULL;
973       } else {
974         prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
975       }
976     }
977   }
978
979 #endif /* LWIP_ND6_LISTEN_RA */
980
981   /* Process our own addresses, updating address lifetimes and/or DAD state. */
982   for (netif = netif_list; netif != NULL; netif = netif->next) {
983     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
984       u8_t addr_state;
985 #if LWIP_IPV6_ADDRESS_LIFETIMES
986       /* Step 1: update address lifetimes (valid and preferred). */
987       addr_state = netif_ip6_addr_state(netif, i);
988       /* RFC 4862 is not entirely clear as to whether address lifetimes affect
989        * tentative addresses, and is even less clear as to what should happen
990        * with duplicate addresses. We choose to track and update lifetimes for
991        * both those types, although for different reasons:
992        * - for tentative addresses, the line of thought of Sec. 5.7 combined
993        *   with the potentially long period that an address may be in tentative
994        *   state (due to the interface being down) suggests that lifetimes
995        *   should be independent of external factors which would include DAD;
996        * - for duplicate addresses, retiring them early could result in a new
997        *   but unwanted attempt at marking them as valid, while retiring them
998        *   late/never could clog up address slots on the netif.
999        * As a result, we may end up expiring addresses of either type here.
1000        */
1001       if (!ip6_addr_isinvalid(addr_state) &&
1002           !netif_ip6_addr_isstatic(netif, i)) {
1003         u32_t life = netif_ip6_addr_valid_life(netif, i);
1004         if (life <= ND6_TMR_INTERVAL / 1000) {
1005           /* The address has expired. */
1006           netif_ip6_addr_set_valid_life(netif, i, 0);
1007           netif_ip6_addr_set_pref_life(netif, i, 0);
1008           netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
1009         } else {
1010           if (!ip6_addr_life_isinfinite(life)) {
1011             life -= ND6_TMR_INTERVAL / 1000;
1012             LWIP_ASSERT("bad valid lifetime", life != IP6_ADDR_LIFE_STATIC);
1013             netif_ip6_addr_set_valid_life(netif, i, life);
1014           }
1015           /* The address is still here. Update the preferred lifetime too. */
1016           life = netif_ip6_addr_pref_life(netif, i);
1017           if (life <= ND6_TMR_INTERVAL / 1000) {
1018             /* This case must also trigger if 'life' was already zero, so as to
1019              * deal correctly with advertised preferred-lifetime reductions. */
1020             netif_ip6_addr_set_pref_life(netif, i, 0);
1021             if (addr_state == IP6_ADDR_PREFERRED)
1022               netif_ip6_addr_set_state(netif, i, IP6_ADDR_DEPRECATED);
1023           } else if (!ip6_addr_life_isinfinite(life)) {
1024             life -= ND6_TMR_INTERVAL / 1000;
1025             netif_ip6_addr_set_pref_life(netif, i, life);
1026           }
1027         }
1028       }
1029       /* The address state may now have changed, so reobtain it next. */
1030 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
1031       /* Step 2: update DAD state. */
1032       addr_state = netif_ip6_addr_state(netif, i);
1033       if (ip6_addr_istentative(addr_state)) {
1034         if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) {
1035           /* No NA received in response. Mark address as valid. For dynamic
1036            * addresses with an expired preferred lifetime, the state is set to
1037            * deprecated right away. That should almost never happen, though. */
1038           addr_state = IP6_ADDR_PREFERRED;
1039 #if LWIP_IPV6_ADDRESS_LIFETIMES
1040           if (!netif_ip6_addr_isstatic(netif, i) &&
1041               netif_ip6_addr_pref_life(netif, i) == 0) {
1042             addr_state = IP6_ADDR_DEPRECATED;
1043           }
1044 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
1045           netif_ip6_addr_set_state(netif, i, addr_state);
1046         } else if (netif_is_up(netif) && netif_is_link_up(netif)) {
1047           /* tentative: set next state by increasing by one */
1048           netif_ip6_addr_set_state(netif, i, addr_state + 1);
1049           /* Send a NS for this address. Use the unspecified address as source
1050            * address in all cases (RFC 4862 Sec. 5.4.2), not in the least
1051            * because as it is, we only consider multicast replies for DAD. */
1052           nd6_send_ns(netif, netif_ip6_addr(netif, i),
1053             ND6_SEND_FLAG_MULTICAST_DEST | ND6_SEND_FLAG_ANY_SRC);
1054         }
1055       }
1056     }
1057   }
1058
1059 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
1060   /* Send router solicitation messages, if necessary. */
1061   for (netif = netif_list; netif != NULL; netif = netif->next) {
1062     if ((netif->rs_count > 0) && netif_is_up(netif) &&
1063         netif_is_link_up(netif) &&
1064         !ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)) &&
1065         !ip6_addr_isduplicated(netif_ip6_addr_state(netif, 0))) {
1066       if (nd6_send_rs(netif) == ERR_OK) {
1067         netif->rs_count--;
1068       }
1069     }
1070   }
1071 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
1072
1073 }
1074
1075 /** Send a neighbor solicitation message for a specific neighbor cache entry
1076  *
1077  * @param entry the neightbor cache entry for wich to send the message
1078  * @param flags one of ND6_SEND_FLAG_*
1079  */
1080 static void
1081 nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags)
1082 {
1083   nd6_send_ns(entry->netif, &entry->next_hop_address, flags);
1084 }
1085
1086 /**
1087  * Send a neighbor solicitation message
1088  *
1089  * @param netif the netif on which to send the message
1090  * @param target_addr the IPv6 target address for the ND message
1091  * @param flags one of ND6_SEND_FLAG_*
1092  */
1093 static void
1094 nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags)
1095 {
1096   struct ns_header *ns_hdr;
1097   struct pbuf *p;
1098   const ip6_addr_t *src_addr;
1099   u16_t lladdr_opt_len;
1100
1101   if (!(flags & ND6_SEND_FLAG_ANY_SRC) &&
1102       ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) {
1103     /* Use link-local address as source address. */
1104     src_addr = netif_ip6_addr(netif, 0);
1105     /* calculate option length (in 8-byte-blocks) */
1106     lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3;
1107   } else {
1108     src_addr = IP6_ADDR_ANY6;
1109     /* Option "MUST NOT be included when the source IP address is the unspecified address." */
1110     lladdr_opt_len = 0;
1111   }
1112
1113   /* Allocate a packet. */
1114   p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + ND6_LLADDR_OPTION_SIZE(netif->hwaddr_len), PBUF_RAM);
1115   if ((p == NULL) || (p->len < (sizeof(struct ns_header) + ND6_LLADDR_OPTION_SIZE(netif->hwaddr_len)))) {
1116     /* We couldn't allocate a suitable pbuf for the ns. drop it. */
1117     if (p != NULL) {
1118       pbuf_free(p);
1119     }
1120     ND6_STATS_INC(nd6.memerr);
1121     return;
1122   }
1123
1124   /* Set fields. */
1125   ns_hdr = (struct ns_header *)p->payload;
1126
1127   ns_hdr->type = ICMP6_TYPE_NS;
1128   ns_hdr->code = 0;
1129   ns_hdr->chksum = 0;
1130   ns_hdr->reserved = 0;
1131   ip6_addr_set(&(ns_hdr->target_address), target_addr);
1132
1133   if (lladdr_opt_len != 0) {
1134     struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header));
1135     lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR;
1136     lladdr_opt->length = ND6_LLADDR_OPTION_LENGTH_ENCODE(netif->hwaddr_len);
1137     SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len);
1138   }
1139
1140   /* Generate the solicited node address for the target address. */
1141   if (flags & ND6_SEND_FLAG_MULTICAST_DEST) {
1142     ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]);
1143     target_addr = &multicast_address;
1144   }
1145
1146 #if CHECKSUM_GEN_ICMP6
1147   IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
1148     ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
1149       target_addr);
1150   }
1151 #endif /* CHECKSUM_GEN_ICMP6 */
1152
1153   /* Send the packet out. */
1154   ND6_STATS_INC(nd6.xmit);
1155   ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr,
1156       LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif);
1157   pbuf_free(p);
1158 }
1159
1160 /**
1161  * Send a neighbor advertisement message
1162  *
1163  * @param netif the netif on which to send the message
1164  * @param target_addr the IPv6 target address for the ND message
1165  * @param flags one of ND6_SEND_FLAG_*
1166  */
1167 static void
1168 nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags)
1169 {
1170   struct na_header *na_hdr;
1171   struct lladdr_option *lladdr_opt;
1172   struct pbuf *p;
1173   const ip6_addr_t *src_addr;
1174   const ip6_addr_t *dest_addr;
1175
1176   /* Use link-local address as source address. */
1177   /* src_addr = netif_ip6_addr(netif, 0); */
1178   /* Use target address as source address. */
1179   src_addr = target_addr;
1180
1181   /* Allocate a packet. */
1182   p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + ND6_LLADDR_OPTION_SIZE(netif->hwaddr_len), PBUF_RAM);
1183   if ((p == NULL) || (p->len < (sizeof(struct na_header) + ND6_LLADDR_OPTION_SIZE(netif->hwaddr_len)))) {
1184     /* We couldn't allocate a suitable pbuf for the ns. drop it. */
1185     if (p != NULL) {
1186       pbuf_free(p);
1187     }
1188     ND6_STATS_INC(nd6.memerr);
1189     return;
1190   }
1191
1192   /* Set fields. */
1193   na_hdr = (struct na_header *)p->payload;
1194   lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
1195
1196   na_hdr->type = ICMP6_TYPE_NA;
1197   na_hdr->code = 0;
1198   na_hdr->chksum = 0;
1199   na_hdr->flags = flags & 0xf0;
1200   na_hdr->reserved[0] = 0;
1201   na_hdr->reserved[1] = 0;
1202   na_hdr->reserved[2] = 0;
1203   ip6_addr_set(&(na_hdr->target_address), target_addr);
1204
1205   lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR;
1206   lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0);
1207   SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len);
1208
1209   /* Generate the solicited node address for the target address. */
1210   if (flags & ND6_SEND_FLAG_MULTICAST_DEST) {
1211     ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]);
1212     dest_addr = &multicast_address;
1213   } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) {
1214     ip6_addr_set_allnodes_linklocal(&multicast_address);
1215     dest_addr = &multicast_address;
1216   } else {
1217     dest_addr = ip6_current_src_addr();
1218   }
1219
1220 #if CHECKSUM_GEN_ICMP6
1221   IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
1222     na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
1223       dest_addr);
1224   }
1225 #endif /* CHECKSUM_GEN_ICMP6 */
1226
1227   /* Send the packet out. */
1228   ND6_STATS_INC(nd6.xmit);
1229   ip6_output_if(p, src_addr, dest_addr,
1230       LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif);
1231   pbuf_free(p);
1232 }
1233
1234 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
1235 /**
1236  * Send a router solicitation message
1237  *
1238  * @param netif the netif on which to send the message
1239  */
1240 static err_t
1241 nd6_send_rs(struct netif *netif)
1242 {
1243   struct rs_header *rs_hdr;
1244   struct lladdr_option *lladdr_opt;
1245   struct pbuf *p;
1246   const ip6_addr_t *src_addr;
1247   err_t err;
1248   u16_t lladdr_opt_len = 0;
1249
1250   /* Link-local source address, or unspecified address? */
1251   if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) {
1252     src_addr = netif_ip6_addr(netif, 0);
1253   } else {
1254     src_addr = IP6_ADDR_ANY6;
1255   }
1256
1257   /* Generate the all routers target address. */
1258   ip6_addr_set_allrouters_linklocal(&multicast_address);
1259
1260   /* Allocate a packet. */
1261   if (src_addr != IP6_ADDR_ANY6) {
1262     lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0);
1263   }
1264   p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM);
1265   if (p == NULL) {
1266     ND6_STATS_INC(nd6.memerr);
1267     return ERR_BUF;
1268   }
1269
1270   /* Set fields. */
1271   rs_hdr = (struct rs_header *)p->payload;
1272
1273   rs_hdr->type = ICMP6_TYPE_RS;
1274   rs_hdr->code = 0;
1275   rs_hdr->chksum = 0;
1276   rs_hdr->reserved = 0;
1277
1278   if (src_addr != IP6_ADDR_ANY6) {
1279     /* Include our hw address. */
1280     lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header));
1281     lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR;
1282     lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0);
1283     SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len);
1284   }
1285
1286 #if CHECKSUM_GEN_ICMP6
1287   IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
1288     rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
1289       &multicast_address);
1290   }
1291 #endif /* CHECKSUM_GEN_ICMP6 */
1292
1293   /* Send the packet out. */
1294   ND6_STATS_INC(nd6.xmit);
1295
1296   err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address,
1297       LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif);
1298   pbuf_free(p);
1299
1300   return err;
1301 }
1302 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
1303
1304 /**
1305  * Search for a neighbor cache entry
1306  *
1307  * @param ip6addr the IPv6 address of the neighbor
1308  * @return The neighbor cache entry index that matched, -1 if no
1309  * entry is found
1310  */
1311 static s8_t
1312 nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr)
1313 {
1314   s8_t i;
1315   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
1316     if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) {
1317       return i;
1318     }
1319   }
1320   return -1;
1321 }
1322
1323 /**
1324  * Create a new neighbor cache entry.
1325  *
1326  * If no unused entry is found, will try to recycle an old entry
1327  * according to ad-hoc "age" heuristic.
1328  *
1329  * @return The neighbor cache entry index that was created, -1 if no
1330  * entry could be created
1331  */
1332 static s8_t
1333 nd6_new_neighbor_cache_entry(void)
1334 {
1335   s8_t i;
1336   s8_t j;
1337   u32_t time;
1338
1339
1340   /* First, try to find an empty entry. */
1341   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
1342     if (neighbor_cache[i].state == ND6_NO_ENTRY) {
1343       return i;
1344     }
1345   }
1346
1347   /* We need to recycle an entry. in general, do not recycle if it is a router. */
1348
1349   /* Next, try to find a Stale entry. */
1350   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
1351     if ((neighbor_cache[i].state == ND6_STALE) &&
1352         (!neighbor_cache[i].isrouter)) {
1353       nd6_free_neighbor_cache_entry(i);
1354       return i;
1355     }
1356   }
1357
1358   /* Next, try to find a Probe entry. */
1359   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
1360     if ((neighbor_cache[i].state == ND6_PROBE) &&
1361         (!neighbor_cache[i].isrouter)) {
1362       nd6_free_neighbor_cache_entry(i);
1363       return i;
1364     }
1365   }
1366
1367   /* Next, try to find a Delayed entry. */
1368   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
1369     if ((neighbor_cache[i].state == ND6_DELAY) &&
1370         (!neighbor_cache[i].isrouter)) {
1371       nd6_free_neighbor_cache_entry(i);
1372       return i;
1373     }
1374   }
1375
1376   /* Next, try to find the oldest reachable entry. */
1377   time = 0xfffffffful;
1378   j = -1;
1379   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
1380     if ((neighbor_cache[i].state == ND6_REACHABLE) &&
1381         (!neighbor_cache[i].isrouter)) {
1382       if (neighbor_cache[i].counter.reachable_time < time) {
1383         j = i;
1384         time = neighbor_cache[i].counter.reachable_time;
1385       }
1386     }
1387   }
1388   if (j >= 0) {
1389     nd6_free_neighbor_cache_entry(j);
1390     return j;
1391   }
1392
1393   /* Next, find oldest incomplete entry without queued packets. */
1394   time = 0;
1395   j = -1;
1396   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
1397     if (
1398         (neighbor_cache[i].q == NULL) &&
1399         (neighbor_cache[i].state == ND6_INCOMPLETE) &&
1400         (!neighbor_cache[i].isrouter)) {
1401       if (neighbor_cache[i].counter.probes_sent >= time) {
1402         j = i;
1403         time = neighbor_cache[i].counter.probes_sent;
1404       }
1405     }
1406   }
1407   if (j >= 0) {
1408     nd6_free_neighbor_cache_entry(j);
1409     return j;
1410   }
1411
1412   /* Next, find oldest incomplete entry with queued packets. */
1413   time = 0;
1414   j = -1;
1415   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
1416     if ((neighbor_cache[i].state == ND6_INCOMPLETE) &&
1417         (!neighbor_cache[i].isrouter)) {
1418       if (neighbor_cache[i].counter.probes_sent >= time) {
1419         j = i;
1420         time = neighbor_cache[i].counter.probes_sent;
1421       }
1422     }
1423   }
1424   if (j >= 0) {
1425     nd6_free_neighbor_cache_entry(j);
1426     return j;
1427   }
1428
1429   /* No more entries to try. */
1430   return -1;
1431 }
1432
1433 /**
1434  * Will free any resources associated with a neighbor cache
1435  * entry, and will mark it as unused.
1436  *
1437  * @param i the neighbor cache entry index to free
1438  */
1439 static void
1440 nd6_free_neighbor_cache_entry(s8_t i)
1441 {
1442   if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) {
1443     return;
1444   }
1445   if (neighbor_cache[i].isrouter) {
1446     /* isrouter needs to be cleared before deleting a neighbor cache entry */
1447     return;
1448   }
1449
1450   /* Free any queued packets. */
1451   if (neighbor_cache[i].q != NULL) {
1452     nd6_free_q(neighbor_cache[i].q);
1453     neighbor_cache[i].q = NULL;
1454   }
1455
1456   neighbor_cache[i].state = ND6_NO_ENTRY;
1457   neighbor_cache[i].isrouter = 0;
1458   neighbor_cache[i].netif = NULL;
1459   neighbor_cache[i].counter.reachable_time = 0;
1460   ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address));
1461 }
1462
1463 /**
1464  * Search for a destination cache entry
1465  *
1466  * @param ip6addr the IPv6 address of the destination
1467  * @return The destination cache entry index that matched, -1 if no
1468  * entry is found
1469  */
1470 static s8_t
1471 nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr)
1472 {
1473   s8_t i;
1474   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
1475     if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) {
1476       return i;
1477     }
1478   }
1479   return -1;
1480 }
1481
1482 /**
1483  * Create a new destination cache entry. If no unused entry is found,
1484  * will recycle oldest entry.
1485  *
1486  * @return The destination cache entry index that was created, -1 if no
1487  * entry was created
1488  */
1489 static s8_t
1490 nd6_new_destination_cache_entry(void)
1491 {
1492   s8_t i, j;
1493   u32_t age;
1494
1495   /* Find an empty entry. */
1496   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
1497     if (ip6_addr_isany(&(destination_cache[i].destination_addr))) {
1498       return i;
1499     }
1500   }
1501
1502   /* Find oldest entry. */
1503   age = 0;
1504   j = LWIP_ND6_NUM_DESTINATIONS - 1;
1505   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
1506     if (destination_cache[i].age > age) {
1507       j = i;
1508     }
1509   }
1510
1511   return j;
1512 }
1513
1514 /**
1515  * Clear the destination cache.
1516  *
1517  * This operation may be necessary for consistency in the light of changing
1518  * local addresses and/or use of the gateway hook.
1519  */
1520 void
1521 nd6_clear_destination_cache(void)
1522 {
1523   int i;
1524
1525   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
1526     ip6_addr_set_any(&destination_cache[i].destination_addr);
1527   }
1528 }
1529
1530 /**
1531  * Determine whether an address matches an on-link prefix or the subnet of a
1532  * statically assigned address.
1533  *
1534  * @param ip6addr the IPv6 address to match
1535  * @return 1 if the address is on-link, 0 otherwise
1536  */
1537 static s8_t
1538 nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif)
1539 {
1540   s8_t i;
1541
1542 #if LWIP_ND6_LISTEN_RA
1543   /* Check to see if the address matches an on-link prefix. */
1544   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
1545     if ((prefix_list[i].netif == netif) &&
1546         (prefix_list[i].invalidation_timer > 0) &&
1547         ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) {
1548       return 1;
1549     }
1550   }
1551 #endif /* LWIP_ND6_LISTEN_RA */
1552
1553   /* Check to see if address prefix matches a manually configured (= static)
1554    * address. Static addresses have an implied /64 subnet assignment. Dynamic
1555    * addresses (from autoconfiguration) have no implied subnet assignment, and
1556    * are thus effectively /128 assignments. See RFC 5942 for more on this. */
1557   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1558     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
1559         netif_ip6_addr_isstatic(netif, i) &&
1560         ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) {
1561       return 1;
1562     }
1563   }
1564   return 0;
1565 }
1566
1567 #if LWIP_IPV6_ROUTER_SUPPORT
1568 /**
1569  * Select a default router for a destination.
1570  *
1571  * This function is used both for routing and for finding a next-hop target for
1572  * a packet. In the former case, the given netif is NULL, and the returned
1573  * router entry must be for a netif suitable for sending packets (up, link up).
1574  * In the latter case, the given netif is not NULL and restricts router choice.
1575  *
1576  * @param ip6addr the destination address
1577  * @param netif the netif for the outgoing packet, if known
1578  * @return the default router entry index, or -1 if no suitable
1579  *         router is found
1580  */
1581 static s8_t
1582 nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif)
1583 {
1584   struct netif *router_netif;
1585   s8_t i, j, valid_router;
1586   static s8_t last_router;
1587
1588   LWIP_UNUSED_ARG(ip6addr); /* @todo match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */
1589
1590   /* @todo: implement default router preference */
1591
1592   /* Look for valid routers. A reachable router is preferred. */
1593   valid_router = -1;
1594   for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) {
1595     /* Is the router netif both set and apppropriate? */
1596     if (default_router_list[i].neighbor_entry != NULL) {
1597       router_netif = default_router_list[i].neighbor_entry->netif;
1598       if ((router_netif != NULL) && (netif != NULL ? netif == router_netif :
1599           (netif_is_up(router_netif) && netif_is_link_up(router_netif)))) {
1600         /* Is the router valid, i.e., reachable or probably reachable as per
1601          * RFC 4861 Sec. 6.3.6? Note that we will never return a router that
1602          * has no neighbor cache entry, due to the netif association tests. */
1603         if (default_router_list[i].neighbor_entry->state != ND6_INCOMPLETE) {
1604           /* Is the router known to be reachable? */
1605           if (default_router_list[i].neighbor_entry->state == ND6_REACHABLE) {
1606             return i; /* valid and reachable - done! */
1607           } else if (valid_router < 0) {
1608             valid_router = i; /* valid but not known to be reachable */
1609           }
1610         }
1611       }
1612     }
1613   }
1614   if (valid_router >= 0) {
1615     return valid_router;
1616   }
1617
1618   /* Look for any router for which we have any information at all. */
1619   /* last_router is used for round-robin selection of incomplete routers, as
1620    * recommended in RFC 4861 Sec. 6.3.6 point (2). Advance only when picking a
1621    * route, to select the same router as next-hop target in the common case. */
1622   if ((netif == NULL) && (++last_router >= LWIP_ND6_NUM_ROUTERS)) {
1623     last_router = 0;
1624   }
1625   i = last_router;
1626   for (j = 0; j < LWIP_ND6_NUM_ROUTERS; j++) {
1627     if (default_router_list[i].neighbor_entry != NULL) {
1628       router_netif = default_router_list[i].neighbor_entry->netif;
1629       if ((router_netif != NULL) && (netif != NULL ? netif == router_netif :
1630           (netif_is_up(router_netif) && netif_is_link_up(router_netif)))) {
1631         return i;
1632       }
1633     }
1634     if (++i >= LWIP_ND6_NUM_ROUTERS) {
1635       i = 0;
1636     }
1637   }
1638
1639   /* no suitable router found. */
1640   return -1;
1641 }
1642
1643 #endif /* LWIP_IPV6_ROUTER_SUPPORT */
1644
1645
1646 #if LWIP_ND6_LISTEN_RA
1647
1648 /**
1649  * Find a router-announced route to the given destination. This route may be
1650  * based on an on-link prefix or a default router.
1651  *
1652  * If a suitable route is found, the returned netif is guaranteed to be in a
1653  * suitable state (up, link up) to be used for packet transmission.
1654  *
1655  * @param ip6addr the destination IPv6 address
1656  * @return the netif to use for the destination, or NULL if none found
1657  */
1658 struct netif *
1659 nd6_find_route(const ip6_addr_t *ip6addr)
1660 {
1661   struct netif *netif;
1662   s8_t i;
1663
1664   /* @todo decide if it makes sense to check the destination cache first */
1665
1666   /* Check if there is a matching on-link prefix. There may be multiple
1667    * matches. Pick the first one that is associated with a suitable netif. */
1668   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) {
1669     netif = prefix_list[i].netif;
1670     if ((netif != NULL) && ip6_addr_netcmp(&prefix_list[i].prefix, ip6addr) &&
1671         netif_is_up(netif) && netif_is_link_up(netif)) {
1672       return netif;
1673     }
1674   }
1675
1676   /* No on-link prefix match. Find a router that can forward the packet. */
1677   i = nd6_select_router(ip6addr, NULL);
1678   if (i >= 0) {
1679     LWIP_ASSERT("selected router must have a neighbor entry",
1680       default_router_list[i].neighbor_entry != NULL);
1681     return default_router_list[i].neighbor_entry->netif;
1682   }
1683
1684   return NULL;
1685 }
1686
1687 /**
1688  * Find an entry for a default router.
1689  *
1690  * @param router_addr the IPv6 address of the router
1691  * @param netif the netif on which the router is found, if known
1692  * @return the index of the router entry, or -1 if not found
1693  */
1694 static s8_t
1695 nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif)
1696 {
1697   s8_t i;
1698
1699   /* Look for router. */
1700   for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) {
1701     if ((default_router_list[i].neighbor_entry != NULL) &&
1702         ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) &&
1703         ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) {
1704       return i;
1705     }
1706   }
1707
1708   /* router not found. */
1709   return -1;
1710 }
1711
1712 /**
1713  * Create a new entry for a default router.
1714  *
1715  * @param router_addr the IPv6 address of the router
1716  * @param netif the netif on which the router is connected, if known
1717  * @return the index on the router table, or -1 if could not be created
1718  */
1719 static s8_t
1720 nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif)
1721 {
1722   s8_t router_index;
1723   s8_t free_router_index;
1724   s8_t neighbor_index;
1725
1726   /* Do we have a neighbor entry for this router? */
1727   neighbor_index = nd6_find_neighbor_cache_entry(router_addr);
1728   if (neighbor_index < 0) {
1729     /* Create a neighbor entry for this router. */
1730     neighbor_index = nd6_new_neighbor_cache_entry();
1731     if (neighbor_index < 0) {
1732       /* Could not create neighbor entry for this router. */
1733       return -1;
1734     }
1735     ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr);
1736     neighbor_cache[neighbor_index].netif = netif;
1737     neighbor_cache[neighbor_index].q = NULL;
1738     neighbor_cache[neighbor_index].state = ND6_INCOMPLETE;
1739     neighbor_cache[neighbor_index].counter.probes_sent = 1;
1740     nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST);
1741   }
1742
1743   /* Mark neighbor as router. */
1744   neighbor_cache[neighbor_index].isrouter = 1;
1745
1746   /* Look for empty entry. */
1747   free_router_index = LWIP_ND6_NUM_ROUTERS;
1748   for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) {
1749     /* check if router already exists (this is a special case for 2 netifs on the same subnet
1750        - e.g. wifi and cable) */
1751     if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ 
1752       return router_index; 
1753     } 
1754     if (default_router_list[router_index].neighbor_entry == NULL) {
1755       /* remember lowest free index to create a new entry */
1756       free_router_index = router_index;
1757     }
1758   }
1759   if (free_router_index < LWIP_ND6_NUM_ROUTERS) {
1760     default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
1761     return free_router_index;
1762   }
1763
1764   /* Could not create a router entry. */
1765
1766   /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */
1767   neighbor_cache[neighbor_index].isrouter = 0;
1768
1769   /* router not found. */
1770   return -1;
1771 }
1772
1773 #endif /* LWIP_ND6_LISTEN_RA */
1774
1775 #if LWIP_ND6_LISTEN_RA
1776
1777 /**
1778  * Find the cached entry for an on-link prefix.
1779  *
1780  * @param prefix the IPv6 prefix that is on-link
1781  * @param netif the netif on which the prefix is on-link
1782  * @return the index on the prefix table, or -1 if not found
1783  */
1784 static s8_t
1785 nd6_get_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif)
1786 {
1787   s8_t i;
1788
1789   /* Look for prefix in list. */
1790   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) {
1791     if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) &&
1792         (prefix_list[i].netif == netif)) {
1793       return i;
1794     }
1795   }
1796
1797   /* Entry not available. */
1798   return -1;
1799 }
1800
1801 /**
1802  * Creates a new entry for an on-link prefix.
1803  *
1804  * @param prefix the IPv6 prefix that is on-link
1805  * @param netif the netif on which the prefix is on-link
1806  * @return the index on the prefix table, or -1 if not created
1807  */
1808 static s8_t
1809 nd6_new_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif)
1810 {
1811   s8_t i;
1812
1813   /* Create new entry. */
1814   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) {
1815     if ((prefix_list[i].netif == NULL) ||
1816         (prefix_list[i].invalidation_timer == 0)) {
1817       /* Found empty prefix entry. */
1818       prefix_list[i].netif = netif;
1819       ip6_addr_set(&(prefix_list[i].prefix), prefix);
1820       return i;
1821     }
1822   }
1823
1824   /* Entry not available. */
1825   return -1;
1826 }
1827
1828 #endif /* LWIP_ND6_LISTEN_RA */
1829
1830 /**
1831  * Determine the next hop for a destination. Will determine if the
1832  * destination is on-link, else a suitable on-link router is selected.
1833  *
1834  * The last entry index is cached for fast entry search.
1835  *
1836  * @param ip6addr the destination address
1837  * @param netif the netif on which the packet will be sent
1838  * @return the neighbor cache entry for the next hop, ERR_RTE if no
1839  *         suitable next hop was found, ERR_MEM if no cache entry
1840  *         could be created
1841  */
1842 static s8_t
1843 nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
1844 {
1845 #ifdef LWIP_HOOK_ND6_GET_GW
1846   const ip6_addr_t *next_hop_addr;
1847 #endif /* LWIP_HOOK_ND6_GET_GW */
1848   s8_t i;
1849
1850 #if LWIP_NETIF_HWADDRHINT
1851   if (netif->addr_hint != NULL) {
1852     /* per-pcb cached entry was given */
1853     u8_t addr_hint = *(netif->addr_hint);
1854     if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) {
1855       nd6_cached_destination_index = addr_hint;
1856     }
1857   }
1858 #endif /* LWIP_NETIF_HWADDRHINT */
1859
1860   /* Look for ip6addr in destination cache. */
1861   if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) {
1862     /* the cached entry index is the right one! */
1863     /* do nothing. */
1864     ND6_STATS_INC(nd6.cachehit);
1865   } else {
1866     /* Search destination cache. */
1867     i = nd6_find_destination_cache_entry(ip6addr);
1868     if (i >= 0) {
1869       /* found destination entry. make it our new cached index. */
1870       nd6_cached_destination_index = i;
1871     } else {
1872       /* Not found. Create a new destination entry. */
1873       i = nd6_new_destination_cache_entry();
1874       if (i >= 0) {
1875         /* got new destination entry. make it our new cached index. */
1876         nd6_cached_destination_index = i;
1877       } else {
1878         /* Could not create a destination cache entry. */
1879         return ERR_MEM;
1880       }
1881
1882       /* Copy dest address to destination cache. */
1883       ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr);
1884
1885       /* Now find the next hop. is it a neighbor? */
1886       if (ip6_addr_islinklocal(ip6addr) ||
1887           nd6_is_prefix_in_netif(ip6addr, netif)) {
1888         /* Destination in local link. */
1889         destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
1890         ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr);
1891       }
1892       else {
1893 #if LWIP_IPV6_ROUTER_SUPPORT
1894         /* We need to select a router. */
1895         i = nd6_select_router(ip6addr, netif);
1896         if (i < 0) {
1897           /* No router found. */
1898           ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr));
1899           return ERR_RTE;
1900         }
1901         destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */
1902         ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address);
1903 #else
1904         ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr));
1905         return ERR_RTE;
1906 #endif /* LWIP_IPV6_ROUTER_SUPPORT */
1907       }
1908     }
1909   }
1910
1911 #if LWIP_NETIF_HWADDRHINT
1912   if (netif->addr_hint != NULL) {
1913     /* per-pcb cached entry was given */
1914     *(netif->addr_hint) = nd6_cached_destination_index;
1915   }
1916 #endif /* LWIP_NETIF_HWADDRHINT */
1917
1918   /* Look in neighbor cache for the next-hop address. */
1919   if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr),
1920                    &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) {
1921     /* Cache hit. */
1922     /* Do nothing. */
1923     ND6_STATS_INC(nd6.cachehit);
1924   } else {
1925     i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr));
1926     if (i >= 0) {
1927       /* Found a matching record, make it new cached entry. */
1928       nd6_cached_neighbor_index = i;
1929     } else {
1930       /* Neighbor not in cache. Make a new entry. */
1931       i = nd6_new_neighbor_cache_entry();
1932       if (i >= 0) {
1933         /* got new neighbor entry. make it our new cached index. */
1934         nd6_cached_neighbor_index = i;
1935       } else {
1936         /* Could not create a neighbor cache entry. */
1937         return ERR_MEM;
1938       }
1939
1940       /* Initialize fields. */
1941       ip6_addr_copy(neighbor_cache[i].next_hop_address,
1942                    destination_cache[nd6_cached_destination_index].next_hop_addr);
1943       neighbor_cache[i].isrouter = 0;
1944       neighbor_cache[i].netif = netif;
1945       neighbor_cache[i].state = ND6_INCOMPLETE;
1946       neighbor_cache[i].counter.probes_sent = 1;
1947       nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST);
1948     }
1949   }
1950
1951   /* Reset this destination's age. */
1952   destination_cache[nd6_cached_destination_index].age = 0;
1953
1954   return nd6_cached_neighbor_index;
1955 }
1956
1957 /**
1958  * Queue a packet for a neighbor.
1959  *
1960  * @param neighbor_index the index in the neighbor cache table
1961  * @param q packet to be queued
1962  * @return ERR_OK if succeeded, ERR_MEM if out of memory
1963  */
1964 static err_t
1965 nd6_queue_packet(s8_t neighbor_index, struct pbuf *q)
1966 {
1967   err_t result = ERR_MEM;
1968   struct pbuf *p;
1969   int copy_needed = 0;
1970 #if LWIP_ND6_QUEUEING
1971   struct nd6_q_entry *new_entry, *r;
1972 #endif /* LWIP_ND6_QUEUEING */
1973
1974   if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) {
1975     return ERR_ARG;
1976   }
1977
1978   /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
1979    * to copy the whole queue into a new PBUF_RAM (see bug #11400)
1980    * PBUF_ROMs can be left as they are, since ROM must not get changed. */
1981   p = q;
1982   while (p) {
1983     if (p->type != PBUF_ROM) {
1984       copy_needed = 1;
1985       break;
1986     }
1987     p = p->next;
1988   }
1989   if (copy_needed) {
1990     /* copy the whole packet into new pbufs */
1991     p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM);
1992     while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) {
1993       /* Free oldest packet (as per RFC recommendation) */
1994 #if LWIP_ND6_QUEUEING
1995       r = neighbor_cache[neighbor_index].q;
1996       neighbor_cache[neighbor_index].q = r->next;
1997       r->next = NULL;
1998       nd6_free_q(r);
1999 #else /* LWIP_ND6_QUEUEING */
2000       pbuf_free(neighbor_cache[neighbor_index].q);
2001       neighbor_cache[neighbor_index].q = NULL;
2002 #endif /* LWIP_ND6_QUEUEING */
2003       p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM);
2004     }
2005     if (p != NULL) {
2006       if (pbuf_copy(p, q) != ERR_OK) {
2007         pbuf_free(p);
2008         p = NULL;
2009       }
2010     }
2011   } else {
2012     /* referencing the old pbuf is enough */
2013     p = q;
2014     pbuf_ref(p);
2015   }
2016   /* packet was copied/ref'd? */
2017   if (p != NULL) {
2018     /* queue packet ... */
2019 #if LWIP_ND6_QUEUEING
2020     /* allocate a new nd6 queue entry */
2021     new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE);
2022     if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) {
2023       /* Free oldest packet (as per RFC recommendation) */
2024       r = neighbor_cache[neighbor_index].q;
2025       neighbor_cache[neighbor_index].q = r->next;
2026       r->next = NULL;
2027       nd6_free_q(r);
2028       new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE);
2029     }
2030     if (new_entry != NULL) {
2031       new_entry->next = NULL;
2032       new_entry->p = p;
2033       if (neighbor_cache[neighbor_index].q != NULL) {
2034         /* queue was already existent, append the new entry to the end */
2035         r = neighbor_cache[neighbor_index].q;
2036         while (r->next != NULL) {
2037           r = r->next;
2038         }
2039         r->next = new_entry;
2040       } else {
2041         /* queue did not exist, first item in queue */
2042         neighbor_cache[neighbor_index].q = new_entry;
2043       }
2044       LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index));
2045       result = ERR_OK;
2046     } else {
2047       /* the pool MEMP_ND6_QUEUE is empty */
2048       pbuf_free(p);
2049       LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p));
2050       /* { result == ERR_MEM } through initialization */
2051     }
2052 #else /* LWIP_ND6_QUEUEING */
2053     /* Queue a single packet. If an older packet is already queued, free it as per RFC. */
2054     if (neighbor_cache[neighbor_index].q != NULL) {
2055       pbuf_free(neighbor_cache[neighbor_index].q);
2056     }
2057     neighbor_cache[neighbor_index].q = p;
2058     LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index));
2059     result = ERR_OK;
2060 #endif /* LWIP_ND6_QUEUEING */
2061   } else {
2062     LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q));
2063     /* { result == ERR_MEM } through initialization */
2064   }
2065
2066   return result;
2067 }
2068
2069 #if LWIP_ND6_QUEUEING
2070 /**
2071  * Free a complete queue of nd6 q entries
2072  *
2073  * @param q a queue of nd6_q_entry to free
2074  */
2075 static void
2076 nd6_free_q(struct nd6_q_entry *q)
2077 {
2078   struct nd6_q_entry *r;
2079   LWIP_ASSERT("q != NULL", q != NULL);
2080   LWIP_ASSERT("q->p != NULL", q->p != NULL);
2081   while (q) {
2082     r = q;
2083     q = q->next;
2084     LWIP_ASSERT("r->p != NULL", (r->p != NULL));
2085     pbuf_free(r->p);
2086     memp_free(MEMP_ND6_QUEUE, r);
2087   }
2088 }
2089 #endif /* LWIP_ND6_QUEUEING */
2090
2091 /**
2092  * Send queued packets for a neighbor
2093  *
2094  * @param i the neighbor to send packets to
2095  */
2096 static void
2097 nd6_send_q(s8_t i)
2098 {
2099   struct ip6_hdr *ip6hdr;
2100   ip6_addr_t dest;
2101 #if LWIP_ND6_QUEUEING
2102   struct nd6_q_entry *q;
2103 #endif /* LWIP_ND6_QUEUEING */
2104
2105   if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) {
2106     return;
2107   }
2108
2109 #if LWIP_ND6_QUEUEING
2110   while (neighbor_cache[i].q != NULL) {
2111     /* remember first in queue */
2112     q = neighbor_cache[i].q;
2113     /* pop first item off the queue */
2114     neighbor_cache[i].q = q->next;
2115     /* Get ipv6 header. */
2116     ip6hdr = (struct ip6_hdr *)(q->p->payload);
2117     /* Create an aligned copy. */
2118     ip6_addr_set(&dest, &(ip6hdr->dest));
2119     /* send the queued IPv6 packet */
2120     (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest);
2121     /* free the queued IP packet */
2122     pbuf_free(q->p);
2123     /* now queue entry can be freed */
2124     memp_free(MEMP_ND6_QUEUE, q);
2125   }
2126 #else /* LWIP_ND6_QUEUEING */
2127   if (neighbor_cache[i].q != NULL) {
2128     /* Get ipv6 header. */
2129     ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload);
2130     /* Create an aligned copy. */
2131     ip6_addr_set(&dest, &(ip6hdr->dest));
2132     /* send the queued IPv6 packet */
2133     (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest);
2134     /* free the queued IP packet */
2135     pbuf_free(neighbor_cache[i].q);
2136     neighbor_cache[i].q = NULL;
2137   }
2138 #endif /* LWIP_ND6_QUEUEING */
2139 }
2140
2141 /**
2142  * A packet is to be transmitted to a specific IPv6 destination on a specific
2143  * interface. Check if we can find the hardware address of the next hop to use
2144  * for the packet. If so, give the hardware address to the caller, which should
2145  * use it to send the packet right away. Otherwise, enqueue the packet for
2146  * later transmission while looking up the hardware address, if possible.
2147  *
2148  * As such, this function returns one of three different possible results:
2149  *
2150  * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now.
2151  * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later.
2152  * - not ERR_OK: something went wrong; forward the error upward in the stack.
2153  *
2154  * @param netif The lwIP network interface on which the IP packet will be sent.
2155  * @param q The pbuf(s) containing the IP packet to be sent.
2156  * @param ip6addr The destination IPv6 address of the packet.
2157  * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning
2158  *        the packet has been queued).
2159  * @return
2160  * - ERR_OK on success, ERR_RTE if no route was found for the packet,
2161  * or ERR_MEM if low memory conditions prohibit sending the packet at all.
2162  */
2163 err_t
2164 nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp)
2165 {
2166   s8_t i;
2167
2168   /* Get next hop record. */
2169   i = nd6_get_next_hop_entry(ip6addr, netif);
2170   if (i < 0) {
2171     /* failed to get a next hop neighbor record. */
2172     return i;
2173   }
2174
2175   /* Now that we have a destination record, send or queue the packet. */
2176   if (neighbor_cache[i].state == ND6_STALE) {
2177     /* Switch to delay state. */
2178     neighbor_cache[i].state = ND6_DELAY;
2179     neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
2180   }
2181   /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */
2182   if ((neighbor_cache[i].state == ND6_REACHABLE) ||
2183       (neighbor_cache[i].state == ND6_DELAY) ||
2184       (neighbor_cache[i].state == ND6_PROBE)) {
2185
2186     /* Tell the caller to send out the packet now. */
2187     *hwaddrp = neighbor_cache[i].lladdr;
2188     return ERR_OK;
2189   }
2190
2191   /* We should queue packet on this interface. */
2192   *hwaddrp = NULL;
2193   return nd6_queue_packet(i, q);
2194 }
2195
2196
2197 /**
2198  * Get the Path MTU for a destination.
2199  *
2200  * @param ip6addr the destination address
2201  * @param netif the netif on which the packet will be sent
2202  * @return the Path MTU, if known, or the netif default MTU
2203  */
2204 u16_t
2205 nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif)
2206 {
2207   s8_t i;
2208
2209   i = nd6_find_destination_cache_entry(ip6addr);
2210   if (i >= 0) {
2211     if (destination_cache[i].pmtu > 0) {
2212       return destination_cache[i].pmtu;
2213     }
2214   }
2215
2216   if (netif != NULL) {
2217     return netif->mtu;
2218   }
2219
2220   return IP6_MIN_MTU;
2221 }
2222
2223
2224 #if LWIP_ND6_TCP_REACHABILITY_HINTS
2225 /**
2226  * Provide the Neighbor discovery process with a hint that a
2227  * destination is reachable. Called by tcp_receive when ACKs are
2228  * received or sent (as per RFC). This is useful to avoid sending
2229  * NS messages every 30 seconds.
2230  *
2231  * @param ip6addr the destination address which is know to be reachable
2232  *                by an upper layer protocol (TCP)
2233  */
2234 void
2235 nd6_reachability_hint(const ip6_addr_t *ip6addr)
2236 {
2237   s8_t i;
2238
2239   /* Find destination in cache. */
2240   if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) {
2241     i = nd6_cached_destination_index;
2242     ND6_STATS_INC(nd6.cachehit);
2243   } else {
2244     i = nd6_find_destination_cache_entry(ip6addr);
2245   }
2246   if (i < 0) {
2247     return;
2248   }
2249
2250   /* Find next hop neighbor in cache. */
2251   if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) {
2252     i = nd6_cached_neighbor_index;
2253     ND6_STATS_INC(nd6.cachehit);
2254   } else {
2255     i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr));
2256   }
2257   if (i < 0) {
2258     return;
2259   }
2260
2261   /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */
2262   if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) {
2263     return;
2264   }
2265
2266   /* Set reachability state. */
2267   neighbor_cache[i].state = ND6_REACHABLE;
2268   neighbor_cache[i].counter.reachable_time = reachable_time;
2269 }
2270 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
2271
2272 /**
2273  * Remove all prefix, neighbor_cache and router entries of the specified netif.
2274  *
2275  * @param netif points to a network interface
2276  */
2277 void
2278 nd6_cleanup_netif(struct netif *netif)
2279 {
2280   u8_t i;
2281 #if LWIP_IPV6_ROUTER_SUPPORT
2282   s8_t router_index;
2283 #endif
2284 #if LWIP_ND6_LISTEN_RA
2285   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
2286     if (prefix_list[i].netif == netif) {
2287       prefix_list[i].netif = NULL;
2288     }
2289   }
2290 #endif
2291   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
2292     if (neighbor_cache[i].netif == netif) {
2293 #if LWIP_IPV6_ROUTER_SUPPORT
2294       for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) {
2295         if (default_router_list[router_index].neighbor_entry == &neighbor_cache[i]) {
2296           default_router_list[router_index].neighbor_entry = NULL;
2297           default_router_list[router_index].flags = 0;
2298         }
2299       }
2300 #endif
2301       neighbor_cache[i].isrouter = 0;
2302       nd6_free_neighbor_cache_entry(i);
2303     }
2304   }
2305 }
2306
2307 #if LWIP_IPV6_MLD
2308 /**
2309  * The state of a local IPv6 address entry is about to change. If needed, join
2310  * or leave the solicited-node multicast group for the address.
2311  *
2312  * @param netif The netif that owns the address.
2313  * @param addr_idx The index of the address.
2314  * @param new_state The new (IP6_ADDR_) state for the address.
2315  */
2316 void
2317 nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state)
2318 {
2319   u8_t old_state, old_member, new_member;
2320
2321   old_state = netif_ip6_addr_state(netif, addr_idx);
2322
2323   /* Determine whether we were, and should be, a member of the solicited-node
2324    * multicast group for this address. For tentative addresses, the group is
2325    * not joined until the address enters the TENTATIVE_1 (or VALID) state. */
2326   old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_DUPLICATED && old_state != IP6_ADDR_TENTATIVE);
2327   new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_DUPLICATED && new_state != IP6_ADDR_TENTATIVE);
2328
2329   if (old_member != new_member) {
2330     ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]);
2331
2332     if (new_member) {
2333       mld6_joingroup_netif(netif, &multicast_address);
2334     } else {
2335       mld6_leavegroup_netif(netif, &multicast_address);
2336     }
2337   }
2338 }
2339 #endif /* LWIP_IPV6_MLD */
2340
2341 #endif /* LWIP_IPV6 && LWIP_IPV6_ND */