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