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