• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file
3  *
4  * Neighbor discovery and stateless address autoconfiguration for IPv6.
5  * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
6  * (Address autoconfiguration).
7  */
8 
9 /*
10  * Copyright (c) 2010 Inico Technologies Ltd.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,
14  * are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  *    this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33  * OF SUCH DAMAGE.
34  *
35  * This file is part of the lwIP TCP/IP stack.
36  *
37  * Author: Ivan Delamer <delamer@inicotech.com>
38  *
39  *
40  * Please coordinate changes and requests with Ivan Delamer
41  * <delamer@inicotech.com>
42  */
43 
44 #include "lwip/opt.h"
45 
46 #if LWIP_IPV6  /* don't build if not configured for use in lwipopts.h */
47 #include "lwip/sys.h"
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 "lwip/lwip_rpl.h"
67 #include <string.h>
68 
69 #if LWIP_NAT64
70 #include "lwip/nat64.h"
71 #endif
72 
73 #ifdef LWIP_HOOK_FILENAME
74 #include LWIP_HOOK_FILENAME
75 #endif
76 
77 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
78 #error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
79 #endif
80 
81 #ifndef ND6_RA_MAX_INTERVAL
82 #define ND6_RA_MAX_INTERVAL 600
83 #endif
84 
85 #ifndef ND6_RA_ROUTER_LIFETIME
86 #define ND6_RA_ROUTER_LIFETIME (3 * (ND6_RA_MAX_INTERVAL))
87 #endif
88 
89 #define EUI_MAC_BROADCAST_MASK 0xff000000ul
90 
91 u32_t is_dup_detect_initialized = 0;
92 sys_sem_t dup_addr_detect;
93 /* Router tables. */
94 struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS];
95 struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS];
96 struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES];
97 struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS];
98 
99 /* Default values, can be updated by a RA message. */
100 u32_t reachable_time = LWIP_ND6_REACHABLE_TIME;
101 u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */
102 
103 /* Index for cache entries. */
104 static u8_t nd6_cached_neighbor_index;
105 static netif_addr_idx_t nd6_cached_destination_index;
106 
107 /* Multicast address holder. */
108 static ip6_addr_t multicast_address;
109 
110 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
111 static u8_t nd6_tmr_rs_reduction;
112 #endif
113 
114 /* Static buffer to parse RA packet options */
115 union ra_options {
116   struct lladdr_option  lladdr;
117   struct mtu_option     mtu;
118   struct prefix_option  prefix;
119 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
120   struct rdnss_option   rdnss;
121 #endif
122 };
123 static union ra_options nd6_ra_buffer;
124 /* Static buffer to parse RD packet options (size of a minium lladdr as biggest option) */
125 static u8_t rd6_ra_buffer[sizeof(struct lladdr_option)];
126 
127 /* Forward declarations. */
128 static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr, const struct netif *netif);
129 static s8_t nd6_new_neighbor_cache_entry(void);
130 static void nd6_free_neighbor_cache_entry(s8_t i);
131 static s16_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
132 static s16_t nd6_new_destination_cache_entry(void);
133 static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
134 static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif);
135 static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif);
136 static s8_t nd6_get_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif);
137 static s8_t nd6_new_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif);
138 static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif);
139 static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q);
140 static void  nd6_free_router(s8_t i);
141 static int   nd6_neighbor_update(struct netif *inp, const struct lladdr_option *lladdr_opt, s8_t i, u32_t flags);
142 #if defined(LWIP_RA_PREFIX_DYNAMIC) && LWIP_RA_PREFIX_DYNAMIC
143 static s8_t nd6_get_onlink_prefix_with_len(const ip6_addr_t *prefix, u8_t len, struct netif *netif);
144 #endif
145 static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags);
146 static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags);
147 
148 #if LWIP_ND6_QUEUEING
149 static void nd6_free_q(struct nd6_q_entry *q);
150 #else /* LWIP_ND6_QUEUEING */
151 #define nd6_free_q(q) pbuf_free(q)
152 #endif /* LWIP_ND6_QUEUEING */
153 static void nd6_send_q(s8_t i);
154 
155 /* Codenomicon for ICMPv6 fails due to redirect. */
156 struct nd6_opt_hdr {
157   u8_t nd_opt_type;
158   u8_t nd_opt_len;
159 } nd6_opt_hdr_t;
160 
161 #ifdef LWIP_TESTBED
nd6_remove_netif_neighbor_cache_entries(struct netif * netif)162 void nd6_remove_netif_neighbor_cache_entries(struct netif *netif)
163 {
164   int i;
165 
166   /* iterate through neighbour cache */
167   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
168     if (neighbor_cache[i].netif == netif) {
169       neighbor_cache[i].isrouter = 0;
170       nd6_free_neighbor_cache_entry(i);
171     }
172   }
173 }
174 #endif
175 
176 #if LWIP_CONF_UPDATE_BEACON_PRIORITY
177 u16_t
lwip_nbr_cache_free_count(void)178 lwip_nbr_cache_free_count(void)
179 {
180   int index;
181   u16_t cnt = 0;
182   for (index = 0; index < LWIP_ND6_NUM_NEIGHBORS; index++) {
183     if (neighbor_cache[index].state == ND6_NO_ENTRY) {
184       cnt++;
185     }
186   }
187 
188   return cnt;
189 }
190 #endif
191 
192 #if LWIP_RIPPLE
193 void *
nd6_add_default_router(const ip6_addr_t * router_addr,u32_t lifetime,struct netif * inp)194 nd6_add_default_router(const ip6_addr_t *router_addr,
195                        u32_t lifetime, /* in seconds mostly */
196                        struct netif *inp)
197 {
198   /* query if entry already exists */
199   s16_t idx;
200 
201   /* Get the matching default router entry. */
202   idx = nd6_get_router(router_addr, inp);
203   if (idx < 0) {
204     /* Create a new router entry. */
205     idx = nd6_new_router(router_addr, inp);
206     if (idx < 0) {
207       /* Could not create a new router entry. */
208       ND6_STATS_INC(nd6.cache_full);
209       return NULL;
210     }
211   }
212 
213   /* Re-set invalidation timer. */
214   if (lifetime != 0) {
215     default_router_list[idx].invalidation_timer = lifetime;
216   }
217   default_router_list[idx].flags = 0;
218   return (void *)&default_router_list[idx];
219 }
220 
221 void
nd6_refresh_destination_cache(const ip6_addr_t * nexthop_addr)222 nd6_refresh_destination_cache(const ip6_addr_t *nexthop_addr)
223 {
224   int idx;
225   if (nexthop_addr == NULL) {
226     for (idx = 0; idx < LWIP_ND6_NUM_DESTINATIONS; idx++) {
227       destination_cache[idx].age = 0;
228       destination_cache[idx].pmtu = 0;
229       ip6_addr_set_any(&destination_cache[idx].destination_addr);
230       ip6_addr_set_any(&destination_cache[idx].next_hop_addr);
231     }
232     return;
233   }
234 
235   for (idx = 0; idx < LWIP_ND6_NUM_DESTINATIONS; idx++) {
236     if (ip6_addr_cmp(nexthop_addr, &(destination_cache[idx].next_hop_addr))) {
237       ip6_addr_set_any(&destination_cache[idx].destination_addr);
238       ip6_addr_set_any(&destination_cache[idx].next_hop_addr);
239     }
240   }
241 }
242 
243 void
nd6_refresh_destination_cache_by_dest(const ip6_addr_t * dest)244 nd6_refresh_destination_cache_by_dest(const ip6_addr_t *dest)
245 {
246   int idx;
247   if (dest == NULL) {
248     return;
249   }
250 
251   for (idx = 0; idx < LWIP_ND6_NUM_DESTINATIONS; idx++) {
252     if (ip6_addr_cmp(dest, &(destination_cache[idx].destination_addr))) {
253       ip6_addr_set_any(&destination_cache[idx].destination_addr);
254       ip6_addr_set_any(&destination_cache[idx].next_hop_addr);
255     }
256   }
257 }
258 
259 void
nd6_refresh_destination_cache_by_prefix_dest(const ip6_addr_t * dest,uint8_t prefix_len)260 nd6_refresh_destination_cache_by_prefix_dest(const ip6_addr_t *dest, uint8_t prefix_len)
261 {
262   int idx;
263   if (dest == NULL) {
264     return;
265   }
266 
267   for (idx = 0; idx < LWIP_ND6_NUM_DESTINATIONS; idx++) {
268     if (ip6_addr_prefix_netcmp(dest, &(destination_cache[idx].destination_addr), prefix_len)) {
269       ip6_addr_set_any(&destination_cache[idx].destination_addr);
270       ip6_addr_set_any(&destination_cache[idx].next_hop_addr);
271     }
272   }
273 }
274 
275 #if LWIP_ND6_DESTINATIONS_OLDTIME
276 static void
nd6_refresh_destination_cache_by_age(s8_t i)277 nd6_refresh_destination_cache_by_age(s8_t i)
278 {
279   LWIP_ASSERT("invalid nd6 destination_cache index\n", (i >= 0 && i < LWIP_ND6_NUM_DESTINATIONS));
280   s32_t k;
281   if (destination_cache[i].age > LWIP_ND6_DESTINATIONS_OLDTIME) {
282     for (k = 0; k < LWIP_ND6_NUM_NEIGHBORS; k++) {
283       if (ip6_addr_cmp(&neighbor_cache[k].next_hop_address, &destination_cache[i].next_hop_addr)) {
284         ip6_addr_set_any(&destination_cache[i].destination_addr);
285         ip6_addr_set_any(&destination_cache[i].next_hop_addr);
286         destination_cache[i].age = 0;
287       }
288     }
289   }
290 }
291 #endif /* LWIP_ND6_DESTINATIONS_OLDTIME */
292 
293 void
nd6_remove_default_router(void * default_route)294 nd6_remove_default_router(void *default_route)
295 {
296   struct nd6_router_list_entry *entry = NULL;
297 
298   if (default_route == NULL) {
299     return;
300   }
301 
302   entry = (struct nd6_router_list_entry *)default_route;
303 
304   if (entry->neighbor_entry != NULL) {
305     nd6_refresh_destination_cache(&(entry->neighbor_entry->next_hop_address));
306     entry->neighbor_entry->isrouter = 0;
307     entry->neighbor_entry = NULL;
308     entry->invalidation_timer = 0;
309     entry->flags = 0;
310   }
311 }
312 
313 err_t
nd6_get_default_router_ip(ip6_addr_t * router_addr,void * default_route)314 nd6_get_default_router_ip(ip6_addr_t *router_addr, void *default_route)
315 {
316   struct nd6_router_list_entry *entry = NULL;
317 
318   if ((router_addr == NULL) || (default_route == NULL)) {
319     return ERR_VAL;
320   }
321 
322   entry = (struct nd6_router_list_entry *)default_route;
323 
324   if (entry->neighbor_entry == NULL) {
325     return ERR_VAL;
326   }
327 
328   ip6_addr_copy_ptr(router_addr, &entry->neighbor_entry->next_hop_address);
329 
330   return ERR_OK;
331 }
332 #endif /* LWIP_RIPPLE */
333 #if LWIP_RIPPLE || (defined LWIP_TESTBED)
334 
335 err_t
nd6_add_neighbor_cache_entry(struct netif * netif,const ip6_addr_t * nbr_addr,const u8_t * addr,const u8_t addrlen,u8_t uc_reason2_add,void * pv_data)336 nd6_add_neighbor_cache_entry(struct netif *netif,
337                              const ip6_addr_t *nbr_addr, const u8_t *addr,
338                              const u8_t addrlen, u8_t uc_reason2_add, void *pv_data)
339 {
340   int idx;
341   LWIP_UNUSED_ARG(uc_reason2_add);
342   LWIP_UNUSED_ARG(pv_data);
343 
344   if ((addr == NULL) || (nbr_addr == NULL)) {
345     return ERR_VAL;
346   }
347   idx = nd6_find_neighbor_cache_entry(nbr_addr, netif);
348   if (idx >= 0) {
349     /* We already have a record for the solicitor. */
350     if (neighbor_cache[idx].state == ND6_INCOMPLETE) {
351       neighbor_cache[idx].netif = netif;
352       if (memcpy_s(neighbor_cache[idx].lladdr, NETIF_MAX_HWADDR_LEN, addr, addrlen) != EOK) {
353         ND6_STATS_INC(nd6.memerr);
354         return ERR_MEM;
355       }
356       neighbor_cache[idx].lladdrlen = addrlen;
357 
358       /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
359       neighbor_cache[idx].state = ND6_DELAY;
360       neighbor_cache[idx].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
361     }
362 
363     LWIP_DEBUGF_LOG0(IP6_DEBUG, "ND6: Found NBR \n");
364   } else {
365     /*
366      * Add their IPv6 address and link-layer address to neighbor cache.
367      * We will need it at least to send a unicast NA message, but most
368      * likely we will also be communicating with this node soon.
369      */
370     idx = nd6_new_neighbor_cache_entry();
371     if (idx < 0) {
372       /*
373        * We couldn't assign a cache entry for this neighbor.
374        * we won't be able to reply. drop it.
375        */
376       ND6_STATS_INC(nd6.cache_full);
377       return ERR_MEM;
378     }
379 
380     neighbor_cache[idx].netif = netif;
381     if (memcpy_s(neighbor_cache[idx].lladdr, NETIF_MAX_HWADDR_LEN, addr, addrlen) != EOK) {
382       ND6_STATS_INC(nd6.memerr);
383       return ERR_MEM;
384     }
385     neighbor_cache[idx].lladdrlen = addrlen;
386     ip6_addr_set(&(neighbor_cache[idx].next_hop_address), nbr_addr);
387 
388     /* Neighbors added by the RPL module we consider to be reachable */
389     neighbor_cache[idx].state = ND6_REACHABLE;
390     neighbor_cache[idx].counter.reachable_time = reachable_time;
391   }
392 
393   return ERR_OK;
394 }
395 #endif /* LWIP_RIPPLE || (defined LWIP_TESTBED) */
396 
nd6_validate_options(u8_t * opt,int opt_len)397 int nd6_validate_options(u8_t *opt, int opt_len)
398 {
399   struct nd6_opt_hdr *nd_opt = (struct nd6_opt_hdr *)opt;
400   int cnt = 0;
401   if ((nd_opt == NULL) || (opt_len < 0)) {
402     return -1;
403   }
404   while (opt_len) {
405     int l;
406     if ((u32_t)opt_len < sizeof(struct nd6_opt_hdr)) {
407       return -1;
408     }
409     l = nd_opt->nd_opt_len << 3;  // multiply by 8 bytes
410     if ((opt_len < l) || (l == 0)) {
411       return -1;
412     }
413     opt_len -= l;
414     nd_opt = (struct nd6_opt_hdr *)(((char *)nd_opt) + l);
415     cnt++;
416   }
417   return cnt;
418 }
419 
420 static int
nd6_neighbor_update(struct netif * inp,const struct lladdr_option * lladdr_opt,s8_t i,u32_t flags)421 nd6_neighbor_update(struct netif *inp, const struct lladdr_option *lladdr_opt, s8_t i, u32_t flags)
422 {
423   s32_t is_llchange = 0; /* Link layer address changes */
424   u8_t is_solicited;     /* Solicited ND message */
425   u8_t is_override;      /* Override LLADDR message */
426   u8_t is_router;        /* Is Router Message */
427   s8_t idx;              /* Router Index */
428 
429   /* Get solicited flag */
430   is_solicited = (flags & ND6_FLAG_SOLICITED);
431   /* Get override flag */
432   is_override  = (flags & ND6_FLAG_OVERRIDE);
433 
434   /*
435    * If the target's Neighbor Cache entry is in the INCOMPLETE state when
436    * the advertisement is received, one of two things happens.  If the
437    * link layer has addresses and no Target Link-Layer Address option is
438    * included, the receiving node SHOULD silently discard the received
439    * advertisement.  Otherwise, the receiving node performs the following
440    * steps:
441 
442    - It records the link-layer address in the Neighbor Cache entry.
443 
444    - If the advertisement's Solicited flag is set, the state of the
445      entry is set to REACHABLE; otherwise, it is set to STALE.
446 
447    - It sets the IsRouter flag in the cache entry based on the Router
448      flag in the received advertisement.
449 
450    - It sends any packets queued for the neighbor awaiting address
451      resolution.
452   */
453   if (neighbor_cache[i].state == ND6_INCOMPLETE) {
454     if (lladdr_opt == NULL) {
455       /* Not a valid message */
456       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NA: Invalid Option.\n"));
457       ND6_STATS_INC(nd6.proterr);
458       return -1;
459     }
460 
461     /* - It records the link-layer address in the Neighbor Cache entry. */
462     if (memcpy_s(neighbor_cache[i].lladdr, NETIF_MAX_HWADDR_LEN, lladdr_opt->addr, inp->hwaddr_len) != EOK) {
463       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NA: memcpy_s error.\n"));
464       ND6_STATS_INC(nd6.memerr);
465       return -1;
466     }
467     neighbor_cache[i].lladdrlen = inp->hwaddr_len;
468 
469     /*
470      * - If the advertisement's Solicited flag is set, the state of the entry is set to REACHABLE;
471      *   otherwise, it is set to STALE.
472      */
473     if (is_solicited) {
474       neighbor_cache[i].state = ND6_REACHABLE;
475       neighbor_cache[i].counter.reachable_time = reachable_time;
476     } else {
477       neighbor_cache[i].state = ND6_STALE;
478     }
479     /* save the interface */
480     neighbor_cache[i].netif = inp;
481   } else {
482     /* Check is there LLADDR change. */
483     if (lladdr_opt != NULL) {
484       is_llchange = !lwip_lladdr_cmp(neighbor_cache[i].lladdr, lladdr_opt->addr, neighbor_cache[i].lladdrlen);
485     }
486     /*
487      * If the Override flag is clear and the supplied link-layer address differs from that in the cache,
488      * then one of two actions takes place:
489      *    a. If the state of the entry is REACHABLE, set it to STALE, but do not update the entry in any other way.
490      */
491     if (!is_override && is_llchange) {
492       if (neighbor_cache[i].state == ND6_REACHABLE) {
493         neighbor_cache[i].state = ND6_STALE;
494       }
495       /* b. Otherwise, the received advertisement should be ignored and MUST NOT update the cache. */
496       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING,
497                   ("ICMPv6 NA: Override flag is clear and LLADDR differs from the cache.\n"));
498       return -1;
499     } else {
500       /*
501        *  - The link-layer address in the Target Link-Layer Address option MUST be inserted in the cache
502        *    (if one is supplied and differs from the already recorded address)
503        */
504       if (is_override || ((lladdr_opt != NULL) && !is_llchange) || (lladdr_opt == NULL)) {
505         /* If target LLADDR option present, insert to cache */
506         if (lladdr_opt != NULL) {
507           if (memcpy_s(neighbor_cache[i].lladdr, NETIF_MAX_HWADDR_LEN, lladdr_opt->addr, inp->hwaddr_len) != EOK) {
508             LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NA: memcpy_s error.\n"));
509             ND6_STATS_INC(nd6.memerr);
510             return -1;
511           }
512           neighbor_cache[i].lladdrlen = inp->hwaddr_len;
513         }
514         /*
515          * - If the advertisement's Solicited flag is set, the state of the entry is set to REACHABLE;
516          *   otherwise, it is set to STALE.
517          */
518         if (is_solicited) {
519           neighbor_cache[i].state = ND6_REACHABLE;
520           neighbor_cache[i].counter.reachable_time = reachable_time;
521         } else if (is_llchange) {
522           neighbor_cache[i].state = ND6_STALE;
523         }
524       }
525     }
526   }
527 
528   /* Get router flag */
529   is_router = (flags & ND6_FLAG_ROUTER) ? 1 : 0;
530 #if LWIP_RIPPLE && LWIP_ND6_ROUTER
531   /* the router should not record other router */
532   if (inp->forwarding != 0) {
533     is_router = 0;
534   }
535 #endif
536 
537   /* In those cases where the IsRouter flag changes from TRUE to FALSE as a result of this update,
538    * the node MUST remove that router from the Default Router List and update the Destination Cache entries
539    * for all destinations using that neighbor as a router as specified in RFC4861 Section 7.3.3.
540    */
541   if (neighbor_cache[i].isrouter && !is_router) {
542     idx = nd6_get_router(ip6_current_src_addr(), inp);
543     /* Remove from Default Router List */
544     nd6_free_router(idx);
545     neighbor_cache[i].isrouter = is_router;
546   }
547 
548   /* Send queued packets, if any. */
549   if (neighbor_cache[i].q != NULL) {
550     nd6_send_q(i);
551   }
552 
553   return 1;
554 }
555 
556 /**
557  * A local address has been determined to be a duplicate. Take the appropriate
558  * action(s) on the address and the interface as a whole.
559  *
560  * @param netif the netif that owns the address
561  * @param addr_idx the index of the address detected to be a duplicate
562  */
563 static void
nd6_duplicate_addr_detected(struct netif * netif,s8_t addr_idx)564 nd6_duplicate_addr_detected(struct netif *netif, s8_t addr_idx)
565 {
566 
567   /* Mark the address as duplicate, but leave its lifetimes alone. If this was
568    * a manually assigned address, it will remain in existence as duplicate, and
569    * as such be unusable for any practical purposes until manual intervention.
570    * If this was an autogenerated address, the address will follow normal
571    * expiration rules, and thus disappear once its valid lifetime expires. */
572   netif_ip6_addr_set_state(netif, addr_idx, IP6_ADDR_DUPLICATED);
573 
574 #if LWIP_IPV6_AUTOCONFIG
575   /* If the affected address was the link-local address that we use to generate
576    * all other addresses, then we should not continue to use those derived
577    * addresses either, so mark them as duplicate as well. For autoconfig-only
578    * setups, this will make the interface effectively unusable, approaching the
579    * intention of RFC 4862 Sec. 5.4.5. @todo implement the full requirements */
580   if (addr_idx == 0) {
581     s8_t i;
582     for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
583       if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
584           !netif_ip6_addr_isstatic(netif, i)) {
585         netif_ip6_addr_set_state(netif, i, IP6_ADDR_DUPLICATED);
586       }
587     }
588   }
589 #endif /* LWIP_IPV6_AUTOCONFIG */
590 }
591 
592 #if LWIP_IPV6_AUTOCONFIG
593 /**
594  * We received a router advertisement that contains a prefix with the
595  * autoconfiguration flag set. Add or update an associated autogenerated
596  * address.
597  *
598  * @param netif the netif on which the router advertisement arrived
599  * @param prefix_opt a pointer to the prefix option data
600  * @param prefix_addr an aligned copy of the prefix address
601  */
602 static void
nd6_process_autoconfig_prefix(struct netif * netif,struct prefix_option * prefix_opt,const ip6_addr_t * prefix_addr)603 nd6_process_autoconfig_prefix(struct netif *netif,
604   struct prefix_option *prefix_opt, const ip6_addr_t *prefix_addr)
605 {
606   ip6_addr_t ip6addr;
607   u32_t valid_life, pref_life;
608   u8_t addr_state;
609   s8_t i, free_idx;
610 
611   /* The caller already checks RFC 4862 Sec. 5.5.3 points (a) and (b). We do
612    * the rest, starting with checks for (c) and (d) here. */
613   valid_life = lwip_htonl(prefix_opt->valid_lifetime);
614   pref_life = lwip_htonl(prefix_opt->preferred_lifetime);
615   if (pref_life > valid_life || ((prefix_opt->prefix_length != 64)
616 #if defined(LWIP_RA_PREFIX_DYNAMIC) && LWIP_RA_PREFIX_DYNAMIC
617                                    && (prefix_opt->prefix_length != LWIP_RA_PREFIX_LONG)
618 #endif
619                                   )) {
620     return; /* silently ignore this prefix for autoconfiguration purposes */
621   }
622 
623   /* If an autogenerated address already exists for this prefix, update its
624    * lifetimes. An address is considered autogenerated if 1) it is not static
625    * (i.e., manually assigned), and 2) there is an advertised autoconfiguration
626    * prefix for it (the one we are processing here). This does not necessarily
627    * exclude the possibility that the address was actually assigned by, say,
628    * DHCPv6. If that distinction becomes important in the future, more state
629    * must be kept. As explained elsewhere we also update lifetimes of tentative
630    * and duplicate addresses. Skip address slot 0 (the link-local address). */
631   for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
632     addr_state = netif_ip6_addr_state(netif, i);
633     if (!ip6_addr_isinvalid(addr_state) && !netif_ip6_addr_isstatic(netif, i) &&
634         !netif_ip6_addr_isdhcp6(netif, i) && ip6_addr_netcmp(prefix_addr, netif_ip6_addr(netif, i))) {
635       /* Update the valid lifetime, as per RFC 4862 Sec. 5.5.3 point (e).
636        * The valid lifetime will never drop to zero as a result of this. */
637       u32_t remaining_life = netif_ip6_addr_valid_life(netif, i);
638       if (valid_life > ND6_2HRS || valid_life > remaining_life) {
639         netif_ip6_addr_set_valid_life(netif, i, valid_life);
640       } else if (remaining_life > ND6_2HRS) {
641         netif_ip6_addr_set_valid_life(netif, i, ND6_2HRS);
642       }
643       LWIP_ASSERT("bad valid lifetime", !netif_ip6_addr_isstatic(netif, i));
644       /* Update the preferred lifetime. No bounds checks are needed here. In
645        * rare cases the advertisement may un-deprecate the address, though.
646        * Deprecation is left to the timer code where it is handled anyway. */
647       if (pref_life > 0 && addr_state == IP6_ADDR_DEPRECATED) {
648         netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
649       }
650       netif_ip6_addr_set_pref_life(netif, i, pref_life);
651       return; /* there should be at most one matching address */
652     }
653   }
654 
655   /* No autogenerated address exists for this prefix yet. See if we can add a
656    * new one. However, if IPv6 autoconfiguration is administratively disabled,
657    * do not generate new addresses, but do keep updating lifetimes for existing
658    * addresses. Also, when adding new addresses, we must protect explicitly
659    * against a valid lifetime of zero, because again, we use that as a special
660    * value. The generated address would otherwise expire immediately anyway.
661    * Finally, the original link-local address must be usable at all. We start
662    * creating addresses even if the link-local address is still in tentative
663    * state though, and deal with the fallout of that upon DAD collision. */
664   addr_state = netif_ip6_addr_state(netif, 0);
665   if (!netif->ip6_autoconfig_enabled || valid_life == IP6_ADDR_LIFE_STATIC ||
666       ip6_addr_isinvalid(addr_state) || ip6_addr_isduplicated(addr_state)) {
667     return;
668   }
669 
670   /* Construct the new address that we intend to use, and then see if that
671    * address really does not exist. It might have been added manually, after
672    * all. As a side effect, find a free slot. Note that we cannot use
673    * netif_add_ip6_address() here, as it would return ERR_OK if the address
674    * already did exist, resulting in that address being given lifetimes. */
675 #if defined(LWIP_RA_PREFIX_DYNAMIC) && LWIP_RA_PREFIX_DYNAMIC
676   if (prefix_opt->prefix_length == LWIP_RA_PREFIX_LONG) {
677     netif_create_ip6_address_80bit_prefix(netif, prefix_addr, &ip6addr);
678   } else
679 #endif
680   {
681     IP6_ADDR(&ip6addr, prefix_addr->addr[0], prefix_addr->addr[1],
682              netif_ip6_addr(netif, 0)->addr[2], netif_ip6_addr(netif, 0)->addr[3]);
683     ip6_addr_assign_zone(&ip6addr, IP6_UNICAST, netif);
684   }
685 
686   free_idx = 0;
687   for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
688     if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
689       if (ip6_addr_cmp(&ip6addr, netif_ip6_addr(netif, i))) {
690         return; /* formed address already exists */
691       }
692     } else if ((free_idx == 0) && !netif_ip6_addr_isdhcp6(netif, i)) {
693       free_idx = i;
694     }
695   }
696   if (free_idx == 0) {
697     return; /* no address slots available, try again on next advertisement */
698   }
699 
700   /* Assign the new address to the interface. */
701   ip_addr_copy_from_ip6(netif->ip6_addr[free_idx], ip6addr);
702 #if defined(LWIP_IP6_DYNAMIC_PREFIX) && LWIP_IP6_DYNAMIC_PREFIX
703   netif->ip6_prefix_len[free_idx] = prefix_opt->prefix_length;
704 #endif
705   netif_ip6_addr_set_valid_life(netif, free_idx, valid_life);
706   netif_ip6_addr_set_pref_life(netif, free_idx, pref_life);
707   /* Mark it as tentative (DAD will be performed if configured). */
708   if (LWIP_IS_DAD_ENABLED(netif)) {
709     netif_ip6_addr_set_state(netif, free_idx, IP6_ADDR_TENTATIVE);
710   } else {
711     netif_ip6_addr_set_state(netif, free_idx, IP6_ADDR_PREFERRED);
712   }
713 }
714 #endif /* LWIP_IPV6_AUTOCONFIG */
715 
716 #if LWIP_ND6_ROUTER
717 static inline struct lladdr_option *
nd6_extract_lladdr_option(struct pbuf * p,u8_t opt_type,u16_t offset)718 nd6_extract_lladdr_option(struct pbuf *p, u8_t opt_type, u16_t offset)
719 {
720   struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t *)p->payload + offset);
721   if ((lladdr_opt->length == 0) || (lladdr_opt->type != opt_type) ||
722       (p->len < (u16_t)(offset + (unsigned int)(lladdr_opt->length << 3)))) {
723     lladdr_opt = NULL;
724   }
725   return lladdr_opt;
726 }
727 
728 #ifdef LWIP_ND6_NETIF_PREFIX
729 static err_t
nd6_get_ra_prefix_from_netif(struct netif * nif,ip6_addr_t * prefix)730 nd6_get_ra_prefix_from_netif(struct netif *nif, ip6_addr_t *prefix)
731 {
732   int i;
733   /* Get prefix of the first global address */
734   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
735     if (!ip6_addr_isvalid(netif_ip6_addr_state(nif, i))) {
736       continue;
737     }
738 
739     if (ip6_addr_islinklocal(netif_ip6_addr(nif, i))) {
740       continue;
741     }
742     /* using fixed prefix len: 64 */
743     prefix->addr[0] = netif_ip6_addr(nif, i)->addr[0];
744     prefix->addr[1] = netif_ip6_addr(nif, i)->addr[1];
745     prefix->addr[2] = 0;
746     prefix->addr[3] = 0;
747     break;
748   }
749 
750   if (i == LWIP_IPV6_NUM_ADDRESSES) {
751     return ERR_IF;
752   }
753 
754   return ERR_OK;
755 }
756 #endif
757 #if LWIP_RIPPLE && defined(LWIP_ND6_DAG_PREFIX)
758 static err_t
nd6_get_ra_prefix_from_dag(const struct netif * nif,ip6_addr_t * prefix)759 nd6_get_ra_prefix_from_dag(const struct netif *nif, ip6_addr_t *prefix)
760 {
761   if (lwip_rpl_get_ra_prefix(nif, prefix) != ERR_OK) {
762     return ERR_VAL;
763   }
764 
765   return ERR_OK;
766 }
767 #endif
768 
769 static err_t
nd6_get_ra_prefix(const struct netif * nif,ip6_addr_t * prefix)770 nd6_get_ra_prefix(const struct netif *nif, ip6_addr_t *prefix)
771 {
772 #if LWIP_RIPPLE && defined(LWIP_ND6_DAG_PREFIX)
773   return nd6_get_ra_prefix_from_dag(nif, prefix);
774 #elif defined(LWIP_ND6_NETIF_PREFIX)
775   return nd6_get_ra_prefix_from_netif(nif, prefix);
776 #else
777   (void)nif;
778   (void)prefix;
779   return ERR_ARG;
780 #endif
781 }
782 
783 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
784 #define ND6_RA_RDNSS_MAX 16
785 #define ND6_OPTION_RDNSS_MAX_LEN  (1 + (2 * (LWIP_ND6_RDNSS_MAX_DNS_SERVERS)))
786 static u8_t
nd6_ra_dns_option_octets(const struct netif * nif)787 nd6_ra_dns_option_octets(const struct netif *nif)
788 {
789   u8_t cnt;
790   u8_t ip4cnt = 0;
791   u8_t ip6cnt = 0;
792   u8_t optlen = 0;
793 
794   cnt = lwip_dns_get_server_cnt(&ip4cnt, &ip6cnt);
795   if ((cnt == 0) || (cnt > ND6_RA_RDNSS_MAX)) {
796     return 0;
797   }
798   /* 2 : base 8 bytes, each ipv6 addr 16 bytes */
799   optlen += 1 + (2 * ip6cnt);
800 
801 #if LWIP_RIPPLE && LWIP_DNS64 && LWIP_NAT64
802   if ((lwip_rpl_is_rpl_netif(nif) == lwIP_TRUE) && (lwip_rpl_is_br() == lwIP_TRUE) &&
803       (nat64_status_check() == NAT64_RET_OK)) {
804     /* 2 : ipv4 convert to ipv6, 16 bytes */
805     optlen += 2 * ip4cnt;
806   }
807 #else
808   (void)nif;
809 #endif
810 
811   if (optlen > ND6_OPTION_RDNSS_MAX_LEN) {
812     optlen = ND6_OPTION_RDNSS_MAX_LEN;
813   }
814 
815   return optlen;
816 }
817 #endif
818 
819 static u16_t
nd6_ra_option_octets(const struct netif * nif)820 nd6_ra_option_octets(const struct netif *nif)
821 {
822   u16_t opt_len;
823   u16_t single_opt_len;
824   single_opt_len = (u16_t)(((sizeof(struct prefix_option)) >> 3) +
825                            (((sizeof(struct prefix_option)) & 0x07) ? 1 : 0));
826   opt_len = single_opt_len;
827 
828   single_opt_len = (u16_t)(((sizeof(struct mtu_option)) >> 3) +
829                            (((sizeof(struct mtu_option)) & 0x07) ? 1 : 0));
830   opt_len += single_opt_len;
831 
832 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
833   single_opt_len = nd6_ra_dns_option_octets(nif);
834   opt_len += single_opt_len;
835 #else
836   (void)nif;
837 #endif
838 
839   return opt_len;
840 }
841 
842 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
843 #define ND6_RDNSS_LIFETIME_INFINITY 0xFFFFFFFFU
844 static err_t
nd6_ra_fill_dns(const struct netif * nif,struct pbuf * p,u16_t * offset)845 nd6_ra_fill_dns(const struct netif *nif, struct pbuf *p, u16_t *offset)
846 {
847   err_t ret;
848   u8_t dns_opt_len;
849   struct rdnss_option *dns_opt = NULL;
850 
851   dns_opt_len = nd6_ra_dns_option_octets(nif);
852   if (dns_opt_len <= 1) {
853     return ERR_VAL;
854   }
855 
856   dns_opt = (struct rdnss_option *)((u8_t *)p->payload + *offset);
857   dns_opt->type = ND6_OPTION_TYPE_RDNSS;
858   dns_opt->length = dns_opt_len;
859   dns_opt->reserved = 0;
860   dns_opt->lifetime = ND6_RDNSS_LIFETIME_INFINITY;
861 
862   ret = lwip_dns_copy_ip6server_addr(nif, (ip6_addr_t *)dns_opt->rdnss_address, (dns_opt_len - 1) >> 1);
863   if (ret != ERR_OK) {
864     return ERR_VAL;
865   }
866 
867   *offset += (dns_opt_len << 3);
868   return ERR_OK;
869 }
870 #endif
871 
872 static err_t
nd6_ra_fill_mtu(struct netif * nif,struct pbuf * p,u16_t * offset)873 nd6_ra_fill_mtu(struct netif *nif, struct pbuf *p, u16_t *offset)
874 {
875   u16_t opt_len;
876   u32_t mtu;
877   struct mtu_option *mtu_opt = NULL;
878 
879   opt_len = (u16_t)(((sizeof(struct mtu_option)) >> 3) +
880                     (((sizeof(struct mtu_option)) & 0x07) ? 1 : 0));
881   mtu_opt = (struct mtu_option *)((u8_t *)p->payload + *offset);
882   mtu_opt->type = ND6_OPTION_TYPE_MTU;
883   mtu_opt->length = (u8_t)opt_len;
884   mtu_opt->reserved = 0;
885   mtu = nif->mtu6;
886 #if LWIP_RIPPLE
887   mtu -= lwip_hbh_len(NULL);
888 #endif
889   mtu_opt->mtu = lwip_htonl(mtu);
890 
891   *offset += (opt_len << 3);
892   return ERR_OK;
893 }
894 
895 static err_t
nd6_ra_fill_prefix(ip6_addr_t * prefix,struct pbuf * p,u16_t * offset)896 nd6_ra_fill_prefix(ip6_addr_t *prefix, struct pbuf *p, u16_t *offset)
897 {
898   struct prefix_option *prefix_opt = NULL;
899   u16_t prefix_opt_len;
900   prefix_opt_len = (u16_t)(((sizeof(struct prefix_option)) >> 3) +
901                            (((sizeof(struct prefix_option)) & 0x07) ? 1 : 0));
902 
903   prefix_opt = (struct prefix_option *)((u8_t *)p->payload + *offset);
904 
905   prefix_opt->type = ND6_OPTION_TYPE_PREFIX_INFO;
906   prefix_opt->length = prefix_opt_len;
907 #if LWIP_RIPPLE && defined(LWIP_RA_PREFIX_DYNAMIC) && LWIP_RA_PREFIX_DYNAMIC
908   if ((lwip_ntohl(prefix->addr[2]) & EUI_MAC_BROADCAST_MASK) == EUI_MAC_BROADCAST_MASK) {
909     prefix_opt->prefix_length = LWIP_RA_PREFIX_LONG;
910   } else
911 #endif
912   {
913     prefix_opt->prefix_length = ND6_PREFIX_FIXED_LEN;
914   }
915   prefix_opt->flags = ND6_PREFIX_FLAG_ON_LINK | ND6_PREFIX_FLAG_AUTONOMOUS;
916   prefix_opt->valid_lifetime = ND6_PREFIX_LIFETIME_INFINITY;
917   prefix_opt->preferred_lifetime = ND6_PREFIX_LIFETIME_INFINITY;
918   prefix_opt->reserved2[0] = 0;
919   prefix_opt->reserved2[1] = 0;
920   prefix_opt->reserved2[2] = 0;
921   prefix_opt->reserved2[3] = 0;
922   prefix_opt->prefix.addr[0] = prefix->addr[0];
923   prefix_opt->prefix.addr[1] = prefix->addr[1];
924 #if LWIP_RIPPLE && defined(LWIP_RA_PREFIX_DYNAMIC) && LWIP_RA_PREFIX_DYNAMIC
925   if ((lwip_ntohl(prefix->addr[2]) & EUI_MAC_BROADCAST_MASK) == EUI_MAC_BROADCAST_MASK) {
926     /* 0xffff0000ul: take highest bits only */
927     prefix_opt->prefix.addr[2] = lwip_htonl(lwip_ntohl(prefix->addr[2]) & 0xffff0000ul);
928   } else
929 #endif
930   {
931     prefix_opt->prefix.addr[2] = 0;
932   }
933   prefix_opt->prefix.addr[3] = 0;
934 
935   *offset += (prefix_opt_len << 3);
936 
937   return ERR_OK;
938 }
939 
940 static err_t
nd6_ra_fill(struct netif * nif,u8_t flags,ip6_addr_t * prefix,struct pbuf * p)941 nd6_ra_fill(struct netif *nif, u8_t flags, ip6_addr_t *prefix, struct pbuf *p)
942 {
943   u16_t offset;
944   struct ra_header *ra_hdr = NULL;
945 
946   /* Set fields. */
947   ra_hdr = (struct ra_header *)p->payload;
948 
949   ra_hdr->type = ICMP6_TYPE_RA;
950   ra_hdr->code = 0;
951   ra_hdr->chksum = 0;
952   ra_hdr->current_hop_limit = 0; /* 0: unspecified */
953   ra_hdr->flags = 0; /* M and O flag, 0: not managed by DHCPv6 or Other */
954   ra_hdr->router_lifetime = lwip_htons(ND6_RA_ROUTER_LIFETIME);
955   ra_hdr->reachable_time = 0; /* 0: unspecified, used by NUD */
956   ra_hdr->retrans_timer = 0; /* 0: unspecified, used by address resolution and NUD */
957 
958   offset = (u16_t)sizeof(struct ra_header);
959   if (nd6_ra_fill_prefix(prefix, p, &offset) != ERR_OK) {
960     LWIP_DEBUGF_LOG0(IP6_DEBUG, "ICMPv6 RA send fail, fill ra prefix error.\n");
961     return ERR_VAL;
962   }
963 
964   if (nd6_ra_fill_mtu(nif, p, &offset) != ERR_OK) {
965     LWIP_DEBUGF(IP6_DEBUG, ("ICMPv6 RA send fail, fill mtu error.\n"));
966     return ERR_VAL;
967   }
968 
969 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
970   if (nd6_ra_fill_dns(nif, p, &offset) != ERR_OK) {
971     LWIP_DEBUGF_LOG0(IP6_DEBUG, "ICMPv6 RA send, without filling ra dns.\n");
972   }
973 #else
974   (void)nif;
975 #endif
976 
977   (void)flags;
978 
979   return ERR_OK;
980 }
981 
982 err_t
nd6_send_ra(struct netif * netif,const ip6_addr_t * target_addr,u8_t flags)983 nd6_send_ra(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags)
984 {
985   struct pbuf *p = NULL;
986   const ip6_addr_t *src_addr = NULL;
987   const ip6_addr_t *dest_addr = NULL;
988   err_t err;
989   ip6_addr_t prefix;
990   u16_t opt_len;
991   struct ra_header *ra_hdr = NULL;
992 
993   if ((netif == NULL) || (netif->ra_enable != lwIP_TRUE) || ((netif->flags & NETIF_FLAG_UP) == 0) ||
994       (ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) {
995     LWIP_DEBUGF(IP6_DEBUG, ("ICMPv6 RA send fail, not enable.\n"));
996     return ERR_IF;
997   }
998 
999   if (nd6_get_ra_prefix(netif, &prefix) != ERR_OK) {
1000     LWIP_DEBUGF(IP6_DEBUG, ("ICMPv6 RA send fail, not prefix.\n"));
1001     return ERR_IF;
1002   }
1003 
1004   /*
1005    * RFC-4861
1006    * Section 4.2 : Router Advertisement Message Format
1007    * Source Address MUST be the link-local address assigned to the interface
1008    * from which this message is sent
1009    */
1010   if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) {
1011     LWIP_DEBUGF(IP6_DEBUG, ("ICMPv6 RA send fail, no link local addr.\n"));
1012     return ERR_IF;
1013   }
1014   src_addr = netif_ip6_addr(netif, 0);
1015 
1016   /* The dest address default should be the all nodes target address. */
1017   if (target_addr == NULL) {
1018     ip6_addr_set_allnodes_linklocal(&multicast_address);
1019     dest_addr = &multicast_address;
1020   } else {
1021     dest_addr = target_addr;
1022   }
1023 
1024   opt_len = nd6_ra_option_octets(netif);
1025   p = pbuf_alloc(PBUF_IP, sizeof(struct ra_header) + (unsigned int)(opt_len << 3), PBUF_RAM);
1026   if (p == NULL) {
1027     ND6_STATS_INC(nd6.memerr);
1028     return ERR_BUF;
1029   }
1030 
1031   ra_hdr = (struct ra_header *)p->payload;
1032   if (nd6_ra_fill(netif, flags, &prefix, p) != ERR_OK) {
1033     LWIP_DEBUGF(IP6_DEBUG, ("ICMPv6 RA send fail, fill ra error.\n"));
1034     ND6_STATS_INC(nd6.err);
1035     (void)pbuf_free(p);
1036     return ERR_VAL;
1037   }
1038 
1039 #if CHECKSUM_GEN_ICMP6
1040   IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
1041     ra_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, dest_addr);
1042   }
1043 #endif /* CHECKSUM_GEN_ICMP6 */
1044 
1045   ND6_STATS_INC(nd6.xmit);
1046   err = ip6_output_if(p, src_addr, dest_addr, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif);
1047   (void)pbuf_free(p);
1048 
1049   return err;
1050 }
1051 
1052 void
nd6_rs_input(struct pbuf * p,struct netif * inp,u8_t flags)1053 nd6_rs_input(struct pbuf *p, struct netif *inp, u8_t flags)
1054 {
1055   struct rs_header *rs_hdr = NULL;
1056   struct lladdr_option *lladdr_opt = NULL;
1057   u8_t naflags = 0;
1058   s8_t i;
1059 
1060   ND6_STATS_INC(nd6.recv);
1061 
1062   /* Check that RS header fits in packet. */
1063   if (p->len < sizeof(struct rs_header)) {
1064     (void)pbuf_free(p);
1065     ND6_STATS_INC(nd6.lenerr);
1066     ND6_STATS_INC(nd6.drop);
1067     return;
1068   }
1069   (void)flags;
1070   /* Check that RS header HL is 255. */
1071   if (IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM) {
1072     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ICMPv6 RS header Hop Limit is not 255, packet dropped.\n"));
1073     (void)pbuf_free(p);
1074     ND6_STATS_INC(nd6.drop);
1075     return;
1076   }
1077 #if LWIP_ND6_ROUTER
1078   if (inp->forwarding != lwIP_TRUE) {
1079     LWIP_DEBUGF(IP6_DEBUG, ("ICMPv6 RS forwarding false, packet dropped.\n"));
1080     (void)pbuf_free(p);
1081     ND6_STATS_INC(nd6.drop);
1082     return;
1083   }
1084 #endif
1085 #if LWIP_RIPPLE
1086   if (lwip_rpl_is_rpl_netif(inp) == lwIP_FALSE) {
1087     LWIP_DEBUGF(IP6_DEBUG, ("not mesh netif, all rs should drop.\n"));
1088     (void)pbuf_free(p);
1089     ND6_STATS_INC(nd6.drop);
1090     return;
1091   }
1092 #endif
1093   rs_hdr = (struct rs_header *)p->payload;
1094   if (rs_hdr->code != 0) {
1095     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1096                 ("ICMPv6 RS header (code %"X8_F") is not zero, packet dropped.\n", rs_hdr->code));
1097     (void)pbuf_free(p);
1098     ND6_STATS_INC(nd6.drop);
1099     return;
1100   }
1101 
1102   /* 2 : Check if there is a link-layer address provided. Only point to it if in this buffer. */
1103   if (p->len >= (sizeof(struct rs_header) + 2)) {
1104     lladdr_opt = nd6_extract_lladdr_option(p, ND6_OPTION_TYPE_SOURCE_LLADDR, (u16_t)sizeof(struct rs_header));
1105   } else {
1106     lladdr_opt = NULL;
1107   }
1108 
1109   /* just drop packets that the src addr is any, or in the rpl network, the multicast ra is not required. */
1110   if (ip6_addr_isany_val((*ip6_current_src_addr())) || (lladdr_opt == NULL)) {
1111     (void)pbuf_free(p);
1112     ND6_STATS_INC(nd6.drop);
1113     return;
1114   }
1115 
1116   /* Codenomicon for ICMPv6 fails due to redirect. */
1117   /* Validate incoming packet - Do not add neighbor cache entry for self */
1118   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
1119     if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
1120         ip6_addr_cmp(ip6_current_src_addr(), netif_ip6_addr(inp, i))) {
1121       /* Not a valid message. */
1122       (void)pbuf_free(p);
1123       ND6_STATS_INC(nd6.proterr);
1124       ND6_STATS_INC(nd6.drop);
1125       return;
1126     }
1127   }
1128 #if LWIP_RIPPLE && LWIP_RPL_RS_DAO
1129   if (flags == ND6_RS_FLAG_DAO) {
1130     if (ip6_addr_isallrouters_linklocal(ip6_current_dest_addr())) {
1131       /* send DAO message */
1132       lwip_rpl_dao_proxy(ip6_current_src_addr(), lladdr_opt->addr, inp->hwaddr_len);
1133       (void)pbuf_free(p);
1134     } else {
1135       /* Not a valid message. */
1136       (void)pbuf_free(p);
1137       ND6_STATS_INC(nd6.proterr);
1138       ND6_STATS_INC(nd6.drop);
1139     }
1140     return;
1141   } else
1142 #endif
1143   {
1144     LWIP_DEBUGF(IP6_DEBUG, ("Will send RA flags[%x]\n", naflags));
1145     (void)nd6_send_ra(inp, ip6_current_src_addr(), naflags);
1146   }
1147 
1148   (void)pbuf_free(p);
1149   return;
1150 }
1151 #endif
1152 
1153 #if LWIP_RIPPLE && defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
1154 static err_t
nd6_na_proxy(ip6_addr_t * src,ip6_addr_t * target,struct netif * inp)1155 nd6_na_proxy(ip6_addr_t *src, ip6_addr_t *target, struct netif *inp)
1156 {
1157   if (ip6_addr_isany_val(*src) || ip6_addr_islinklocal(target)) {
1158     return ERR_ARG;
1159   }
1160 
1161   if (lwip_rpl_is_rpl_netif(inp)) {
1162     /* only the non-mesh node be proxy */
1163     return lwip_rpl_nonmesh_node(src);
1164   } else if (lwip_rpl_is_br()) {
1165     /* the node behind the MBR will be proxy */
1166     return lwip_rpl_behind_mbr_node(target);
1167   }
1168 
1169   return ERR_VAL;
1170 }
1171 #endif
1172 
1173 /**
1174  * Process an incoming neighbor discovery message
1175  *
1176  * @param p the nd packet, p->payload pointing to the icmpv6 header
1177  * @param inp the netif on which this packet was received
1178  */
1179 void
nd6_input(struct pbuf * p,struct netif * inp)1180 nd6_input(struct pbuf *p, struct netif *inp)
1181 {
1182   u8_t msg_type;
1183   s8_t i;
1184   s16_t dest_idx;
1185 
1186   ND6_STATS_INC(nd6.recv);
1187 
1188   msg_type = *((u8_t *)p->payload);
1189 #if LWIP_RIPPLE && defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
1190   if ((p->na_proxy == lwIP_TRUE) && (msg_type != ICMP6_TYPE_NS)) {
1191     (void)pbuf_free(p);
1192     return;
1193   }
1194 #endif
1195   switch (msg_type) {
1196   case ICMP6_TYPE_NA: /* Neighbor Advertisement. */
1197   {
1198     struct na_header *na_hdr;
1199     struct lladdr_option *lladdr_opt;
1200     ip6_addr_t target_address;
1201     int ret;
1202 
1203     /* Check that na header fits in packet. */
1204     if (p->len < (sizeof(struct na_header))) {
1205       /* @todo debug message */
1206       pbuf_free(p);
1207       ND6_STATS_INC(nd6.lenerr);
1208       ND6_STATS_INC(nd6.drop);
1209       return;
1210     }
1211 
1212     na_hdr = (struct na_header *)p->payload;
1213 
1214     /* Create an aligned, zoned copy of the target address. */
1215     ip6_addr_copy_from_packed(target_address, na_hdr->target_address);
1216     ip6_addr_assign_zone(&target_address, IP6_UNICAST, inp);
1217 
1218     /* Check a subset of the other RFC 4861 Sec. 7.1.2 requirements. */
1219     if (IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || na_hdr->code != 0 ||
1220         ip6_addr_ismulticast(&target_address)) {
1221       pbuf_free(p);
1222       ND6_STATS_INC(nd6.proterr);
1223       ND6_STATS_INC(nd6.drop);
1224       return;
1225     }
1226 
1227     /* @todo RFC MUST: if IP destination is multicast, Solicited flag is zero */
1228     /* @todo RFC MUST: all included options have a length greater than zero */
1229 
1230     /* Unsolicited NA?*/
1231     if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
1232       /* This is an unsolicited NA.
1233        * link-layer changed?
1234        * part of DAD mechanism? */
1235 
1236       /*
1237        * Check RFC 4861 Sec. 7.1.2 requirements: If the IP Destination Address is a multicast address the
1238        * Solicited flag is zero, Silently discard any received Neighbor Advertisement.
1239        */
1240       if (na_hdr->flags & ND6_FLAG_SOLICITED) {
1241         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NA: solicited NA is multicasted.\n"));
1242         (void)pbuf_free(p);
1243         ND6_STATS_INC(nd6.proterr);
1244         ND6_STATS_INC(nd6.drop);
1245         return;
1246       }
1247 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1248       /* If the target address matches this netif, it is a DAD response. */
1249       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1250         if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
1251             !ip6_addr_isduplicated(netif_ip6_addr_state(inp, i)) &&
1252             ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) {
1253           /* [Ignore the NA tgt address same as stack address ] */
1254           if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i))) {
1255             /* just ignore the packet and do not process it further */
1256             (void)pbuf_free(p);
1257             ND6_STATS_INC(nd6.drop);
1258             return;
1259           }
1260           /* We are using a duplicate address. */
1261           nd6_duplicate_addr_detected(inp, i);
1262 
1263           if (inp->ipv6_addr_event_cb != NULL) {
1264             inp->ipv6_addr_event_cb(inp, *netif_ip6_addr(inp, i), netif_ip6_addr_state(inp, i));
1265           }
1266 
1267           if (is_dup_detect_initialized) {
1268             sys_sem_signal(&dup_addr_detect);
1269           }
1270           /* Once DAD on link local fails, it is not supposed to send/recv anything */
1271           if (ip6_addr_islinklocal(&target_address) && (i == 0)) {
1272             (void)netif_set_down(inp);
1273           } else {
1274 #if LWIP_IPV6_DHCP6 && LWIP_IPV6_DHCP6_STATEFUL
1275             dhcp6_dad_handle(inp, &target_address);
1276 #endif
1277           }
1278           pbuf_free(p);
1279           return;
1280         }
1281       }
1282 #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
1283 
1284       /* Check that link-layer address option also fits in packet. */
1285       if (p->len < (sizeof(struct na_header) + 2)) {
1286         /* @todo debug message */
1287         pbuf_free(p);
1288         ND6_STATS_INC(nd6.lenerr);
1289         ND6_STATS_INC(nd6.drop);
1290         return;
1291       }
1292 
1293       lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
1294 
1295       if ((lladdr_opt->length == 0) || (lladdr_opt->type != ND6_OPTION_TYPE_TARGET_LLADDR) ||
1296           (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3)))) {
1297         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NA: Invalid Option.\n"));
1298         pbuf_free(p);
1299         ND6_STATS_INC(nd6.lenerr);
1300         ND6_STATS_INC(nd6.drop);
1301         return;
1302       }
1303 
1304       /* This is an unsolicited NA, most likely there was a LLADDR change. */
1305       i = nd6_find_neighbor_cache_entry(&target_address, inp);
1306       if (i < 0) {
1307         /* Entry is not present in the Cache,drop it. */
1308         ND6_STATS_INC(nd6.cache_miss);
1309         (void)pbuf_free(p);
1310         return;
1311       }
1312     } else {
1313       /* This is a solicited NA.
1314        * neighbor address resolution response?
1315        * neighbor unreachability detection response? */
1316 
1317       /* Find the cache entry corresponding to this na. */
1318       i = nd6_find_neighbor_cache_entry(&target_address, inp);
1319       if (i < 0) {
1320         /* We no longer care about this target address. drop it. */
1321         ND6_STATS_INC(nd6.cache_miss);
1322         pbuf_free(p);
1323         return;
1324       }
1325 
1326       /* Check if there is a link-layer address provided. Only point to it if in this buffer. */
1327       /* 2 is struct lladdr_option's type and code size */
1328       if (p->len >= (sizeof(struct na_header) + 2)) {
1329         lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
1330 
1331         if ((!lladdr_opt->length) || (lladdr_opt->type != ND6_OPTION_TYPE_TARGET_LLADDR) ||
1332             p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) {
1333           lladdr_opt = NULL;
1334         }
1335         /* Yes Option is valid */
1336       } else {
1337         /* No LLADDR option or Invalid */
1338         lladdr_opt = NULL;
1339       }
1340     }
1341 
1342     /* Update Neighbor cache entries */
1343     ret = nd6_neighbor_update(inp, lladdr_opt, i, na_hdr->flags);
1344     if (ret < 0) {
1345       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ICMPv6 neighbor update failed ret(%"S32_F").\n", ret));
1346       ND6_STATS_INC(nd6.drop);
1347       (void)pbuf_free(p);
1348       return;
1349     }
1350 
1351     break; /* ICMP6_TYPE_NA */
1352   }
1353   case ICMP6_TYPE_NS: /* Neighbor solicitation. */
1354   {
1355     struct ns_header *ns_hdr;
1356     struct lladdr_option *lladdr_opt;
1357     ip6_addr_t target_address;
1358     u8_t accepted;
1359     u8_t naflags = 0;
1360 
1361     /* Check that ns header fits in packet. */
1362     if (p->len < sizeof(struct ns_header)) {
1363       /* @todo debug message */
1364       pbuf_free(p);
1365       ND6_STATS_INC(nd6.lenerr);
1366       ND6_STATS_INC(nd6.drop);
1367       return;
1368     }
1369 
1370     ns_hdr = (struct ns_header *)p->payload;
1371 
1372     /* Create an aligned, zoned copy of the target address. */
1373     ip6_addr_copy_from_packed(target_address, ns_hdr->target_address);
1374     ip6_addr_assign_zone(&target_address, IP6_UNICAST, inp);
1375 
1376     /* Check a subset of the other RFC 4861 Sec. 7.1.1 requirements. */
1377     if (IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || ns_hdr->code != 0 ||
1378        ip6_addr_ismulticast(&target_address)) {
1379       pbuf_free(p);
1380       ND6_STATS_INC(nd6.proterr);
1381       ND6_STATS_INC(nd6.drop);
1382       return;
1383     }
1384 
1385     /* @todo RFC MUST: all included options have a length greater than zero */
1386     /* @todo RFC MUST: if IP source is 'any', destination is solicited-node multicast address */
1387     /* @todo RFC MUST: if IP source is 'any', there is no source LL address option */
1388 
1389     /* Check if there is a link-layer address provided. Only point to it if in this buffer. */
1390     if (p->len >= (sizeof(struct ns_header) + 2)) {
1391       lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header));
1392       if ((lladdr_opt == NULL) || (!lladdr_opt->length) || (lladdr_opt->type != ND6_OPTION_TYPE_SOURCE_LLADDR) ||
1393           p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) {
1394         lladdr_opt = NULL;
1395       } else {
1396         /*
1397          * Check RFC 4861 Sec. 7.1.1 requirements: If the IP source address is the unspecified address,
1398          * there is no source link-layer address option in the message.
1399          */
1400         if (ip6_addr_isany_val(*(ip6_current_src_addr()))) {
1401           (void)pbuf_free(p);
1402           ND6_STATS_INC(nd6.proterr);
1403           ND6_STATS_INC(nd6.drop);
1404           return;
1405         }
1406       }
1407     } else {
1408       lladdr_opt = NULL;
1409     }
1410 
1411     /* Check if the target address is configured on the receiving netif. */
1412     accepted = 0;
1413     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
1414       if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) ||
1415            (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) &&
1416            ip6_addr_isany_val((*ip6_current_src_addr())))) &&
1417           ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) {
1418         accepted = 1;
1419         break;
1420       }
1421     }
1422 
1423 #if LWIP_RIPPLE && defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
1424     if ((accepted == 0) &&
1425         (nd6_na_proxy(ip6_current_src_addr(), (ip6_addr_t *)&ns_hdr->target_address, inp) == ERR_OK)) {
1426       accepted = 1;
1427     }
1428 #endif
1429 
1430     /* NS not for us? */
1431     if (!accepted) {
1432       pbuf_free(p);
1433       return;
1434     }
1435 
1436     /* Check for ANY address in src (DAD algorithm). */
1437     if (ip6_addr_isany_val((*ip6_current_src_addr()))) {
1438       /* Sender is validating this address. */
1439       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
1440         if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
1441             ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) {
1442             naflags = (ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST);
1443           if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) {
1444             /* We shouldn't use this address either. */
1445             nd6_duplicate_addr_detected(inp, i);
1446             /* do not use any of address on this interface */
1447             /* Once DAD on link local fails, it is not supposed to send/recv anything */
1448             if (ip6_addr_islinklocal(netif_ip6_addr(inp, i)) && (i == 0)) {
1449               (void)netif_set_down(inp);
1450               (void)pbuf_free(p);
1451               return;
1452             } else {
1453 #if LWIP_IPV6_DHCP6 && LWIP_IPV6_DHCP6_STATEFUL
1454               dhcp6_dad_handle(inp, &target_address);
1455 #endif
1456             }
1457           } else {
1458             /* Send a NA back so that the sender does not use this address. */
1459             nd6_send_na(inp, netif_ip6_addr(inp, i), naflags);
1460           }
1461         }
1462       }
1463     } else {
1464       /* Sender is trying to resolve our address. */
1465       /* Verify that they included their own link-layer address. */
1466       if (lladdr_opt == NULL) {
1467         /* Not a valid message. */
1468         pbuf_free(p);
1469         ND6_STATS_INC(nd6.proterr);
1470         ND6_STATS_INC(nd6.drop);
1471         return;
1472       }
1473 
1474       /* Codenomicon for ICMPv6 fails due to redirect. */
1475       /* Validate incoming packet - Do not add neighbor cache entry for self */
1476       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
1477         if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
1478             ip6_addr_cmp(ip6_current_src_addr(), netif_ip6_addr(inp, i))) {
1479             /* Not a valid message. */
1480             (void)pbuf_free(p);
1481             ND6_STATS_INC(nd6.proterr);
1482             ND6_STATS_INC(nd6.drop);
1483             return;
1484         }
1485       }
1486       i = nd6_find_neighbor_cache_entry(ip6_current_src_addr(), inp);
1487       if (i>= 0) {
1488         /* We already have a record for the solicitor. */
1489         if (neighbor_cache[i].state == ND6_INCOMPLETE) {
1490           neighbor_cache[i].netif = inp;
1491           MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
1492           neighbor_cache[i].lladdrlen = inp->hwaddr_len;
1493 
1494           /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */
1495           neighbor_cache[i].state = ND6_DELAY;
1496           neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
1497         }
1498       } else {
1499         /* Add their IPv6 address and link-layer address to neighbor cache.
1500          * We will need it at least to send a unicast NA message, but most
1501          * likely we will also be communicating with this node soon. */
1502         i = nd6_new_neighbor_cache_entry();
1503         if (i < 0) {
1504           /* We couldn't assign a cache entry for this neighbor.
1505            * we won't be able to reply. drop it. */
1506           pbuf_free(p);
1507           ND6_STATS_INC(nd6.cache_full);
1508           return;
1509         }
1510         neighbor_cache[i].netif = inp;
1511         MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
1512         neighbor_cache[i].lladdrlen = inp->hwaddr_len;
1513         ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr());
1514 
1515         /* Receiving a message does not prove reachability: only in one direction.
1516          * Delay probe in case we get confirmation of reachability from upper layer (TCP). */
1517         neighbor_cache[i].state = ND6_DELAY;
1518         neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
1519       }
1520 
1521       /* Send back a NA for us. Allocate the reply pbuf. */
1522       naflags = ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE;
1523 
1524       /* If the node acts as a router in the RPL mesh network it can set the ND6_FLAG_ROUTER in the NA message */
1525 #if LWIP_RIPPLE && LWIP_ND6_ROUTER
1526       if ((inp->forwarding != lwIP_FALSE)
1527 #if defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
1528           && (p->na_proxy != lwIP_TRUE)
1529 #endif
1530          ) {
1531         naflags |= ND6_FLAG_ROUTER;
1532       }
1533 #endif
1534 
1535       LWIP_DEBUGF(IP6_DEBUG, ("Will send NA flags[%x]", naflags));
1536       nd6_send_na(inp, &target_address, naflags);
1537     }
1538 
1539     break; /* ICMP6_TYPE_NS */
1540   }
1541   case ICMP6_TYPE_RA: /* Router Advertisement. */
1542   {
1543     struct ra_header *ra_hdr;
1544     u8_t *buffer; /* Used to copy options. */
1545     u16_t offset;
1546     /* flag indicated that whether there was already one default router cache or need to create a new one. */
1547     u8_t exist_or_new;
1548 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
1549     /* There can be multiple RDNSS options per RA */
1550     u8_t rdnss_server_idx = 0;
1551 #endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
1552 #if LWIP_ND6_ROUTER
1553     if ((inp->accept_ra != lwIP_TRUE) || (inp->forwarding != lwIP_FALSE)) {
1554       LWIP_DEBUGF(IP6_DEBUG, ("ICMPv6 RA not accept, packet dropped.\n"));
1555       (void)pbuf_free(p);
1556       ND6_STATS_INC(nd6.drop);
1557       return;
1558     }
1559 #endif
1560     /* Check that RA header fits in packet. */
1561     if (p->len < sizeof(struct ra_header)) {
1562       /* @todo debug message */
1563       pbuf_free(p);
1564       ND6_STATS_INC(nd6.lenerr);
1565       ND6_STATS_INC(nd6.drop);
1566       return;
1567     }
1568 
1569     ra_hdr = (struct ra_header *)p->payload;
1570 
1571     /* Check a subset of the other RFC 4861 Sec. 6.1.2 requirements. */
1572     if (!ip6_addr_islinklocal(ip6_current_src_addr()) ||
1573         IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || ra_hdr->code != 0) {
1574       pbuf_free(p);
1575       ND6_STATS_INC(nd6.proterr);
1576       ND6_STATS_INC(nd6.drop);
1577       return;
1578     }
1579 
1580     /* @todo RFC MUST: all included options have a length greater than zero */
1581 
1582     /* If we are sending RS messages, stop. */
1583 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
1584     /* ensure at least one solicitation is sent (see RFC 4861, ch. 6.3.7) */
1585     if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) ||
1586         (nd6_send_rs(inp) == ERR_OK)) {
1587       inp->rs_count = 0;
1588     } else {
1589       inp->rs_count = 1;
1590     }
1591 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
1592 
1593     /* Get the matching default router entry. */
1594     i = nd6_get_router(ip6_current_src_addr(), inp);
1595     if (i < 0) {
1596       if (lwip_htons(ra_hdr->router_lifetime) != 0) {
1597         /* Create a new router entry. */
1598         i = nd6_new_router(ip6_current_src_addr(), inp);
1599 
1600         if (i < 0) {
1601           /* Could not create a new router entry. */
1602           pbuf_free(p);
1603           ND6_STATS_INC(nd6.cache_full);
1604           return;
1605         } else {
1606           exist_or_new = 1;
1607         }
1608       } else {
1609         exist_or_new = 0;
1610       }
1611     } else {
1612       exist_or_new = 1;
1613     }
1614 
1615     if (exist_or_new) {
1616       /* RA update: Remove the entry from default router list immediately rather than waiting for timer expiry */
1617       if (ra_hdr->router_lifetime == 0) {
1618         nd6_free_router(i);
1619       } else {
1620         /* Re-set invalidation timer. */
1621         default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime);
1622         /* Update flags in local entry (incl. preference). */
1623         default_router_list[i].flags = ra_hdr->flags;
1624       }
1625     }
1626     /* Re-set default timer values. */
1627 #if LWIP_ND6_ALLOW_RA_UPDATES
1628     if (ra_hdr->retrans_timer > 0) {
1629       retrans_timer = lwip_htonl(ra_hdr->retrans_timer);
1630     }
1631     if (ra_hdr->reachable_time > 0) {
1632       reachable_time = lwip_htonl(ra_hdr->reachable_time);
1633     }
1634 #endif /* LWIP_ND6_ALLOW_RA_UPDATES */
1635 
1636 #if LWIP_IPV6_DHCP6
1637     /* Trigger DHCPv6 if enabled */
1638     dhcp6_nd6_ra_trigger(inp, ra_hdr->flags & ND6_RA_FLAG_MANAGED_ADDR_CONFIG,
1639       ra_hdr->flags & ND6_RA_FLAG_OTHER_CONFIG);
1640 #endif
1641 
1642     /* Offset to options. */
1643     offset = sizeof(struct ra_header);
1644 
1645     /* Validate option. */
1646     while ((p->tot_len - offset) >= 2) {
1647       u8_t option_type;
1648       u16_t option_len;
1649       int option_len8 = pbuf_try_get_at(p, offset + 1);
1650       if (option_len8 <= 0) {
1651         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1652                     ("IPv6 options header (optlen %d) is not specified, packet dropped.\n",
1653                      option_len8));
1654         /* read beyond end or zero length */
1655         goto lenerr_drop_free_return;
1656       }
1657       option_len = ((u8_t)option_len8) << 3;
1658       if (option_len > p->tot_len - offset) {
1659         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IPv6 options header (optlen %d) does not fit in \
1660           (total len %"U16_F") and (offset %"U16_F"), packet dropped.\n",
1661            option_len8, p->tot_len, offset));
1662         /* short packet (option does not fit in) */
1663         goto lenerr_drop_free_return;
1664       }
1665       if (p->len == p->tot_len) {
1666         /* no need to copy from contiguous pbuf */
1667         buffer = &((u8_t*)p->payload)[offset];
1668       } else {
1669         /* check if this option fits into our buffer */
1670         if (option_len > sizeof(nd6_ra_buffer)) {
1671           option_type = pbuf_get_at(p, offset);
1672           /* invalid option length */
1673           if (option_type != ND6_OPTION_TYPE_RDNSS) {
1674             goto lenerr_drop_free_return;
1675           }
1676           /* we allow RDNSS option to be longer - we'll just drop some servers */
1677           option_len = sizeof(nd6_ra_buffer);
1678         }
1679         buffer = (u8_t*)&nd6_ra_buffer;
1680         option_len = pbuf_copy_partial(p, &nd6_ra_buffer, option_len, offset);
1681       }
1682       option_type = buffer[0];
1683       switch (option_type) {
1684       case ND6_OPTION_TYPE_SOURCE_LLADDR:
1685       {
1686         struct lladdr_option *lladdr_opt;
1687         if (option_len < sizeof(struct lladdr_option)) {
1688           LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1689                       ("ND6_OPTION_TYPE_SOURCE_LLADDR: (optlen %"U16_F") is less than \
1690                       struct lladdr_option or not same as HWADDR length, packet dropped.\n", option_len));
1691           goto lenerr_drop_free_return;
1692         }
1693         lladdr_opt = (struct lladdr_option *)buffer;
1694         if (exist_or_new &&
1695             (default_router_list[i].neighbor_entry != NULL) &&
1696             (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) {
1697           SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len);
1698           default_router_list[i].neighbor_entry->lladdrlen = inp->hwaddr_len;
1699           default_router_list[i].neighbor_entry->state = ND6_REACHABLE;
1700           default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time;
1701         }
1702         break;
1703       }
1704       case ND6_OPTION_TYPE_MTU:
1705       {
1706         struct mtu_option *mtu_opt;
1707         u32_t mtu32;
1708         if (option_len < sizeof(struct mtu_option)) {
1709           goto lenerr_drop_free_return;
1710         }
1711         mtu_opt = (struct mtu_option *)buffer;
1712         mtu32 = lwip_htonl(mtu_opt->mtu);
1713         if ((mtu32 >= IP6_MIN_MTU_LENGTH) && (mtu32 <= 0xffff)) {
1714 #if LWIP_ND6_ALLOW_RA_UPDATES
1715           if (inp->mtu) {
1716             /* don't set the mtu for IPv6 higher than the netif driver supports */
1717             inp->mtu6 = LWIP_MIN(LWIP_MIN(inp->mtu, inp->mtu6), (u16_t)mtu32);
1718           } else {
1719             inp->mtu6 = (u16_t)mtu32;
1720           }
1721 #endif /* LWIP_ND6_ALLOW_RA_UPDATES */
1722         }
1723         break;
1724       }
1725       case ND6_OPTION_TYPE_PREFIX_INFO:
1726       {
1727         struct prefix_option *prefix_opt;
1728         ip6_addr_t prefix_addr;
1729         u8_t prefix_len;
1730         if (option_len < sizeof(struct prefix_option)) {
1731           LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1732                       ("ND6_OPTION_TYPE_PREFIX_INFO: (optlen %"U16_F") is less than \
1733                       struct prefix_option, packet dropped.\n", option_len));
1734           goto lenerr_drop_free_return;
1735         }
1736 
1737         prefix_opt = (struct prefix_option *)buffer;
1738 
1739         /* Get a memory-aligned copy of the prefix. */
1740         ip6_addr_copy_from_packed(prefix_addr, prefix_opt->prefix);
1741         ip6_addr_assign_zone(&prefix_addr, IP6_UNICAST, inp);
1742         prefix_len = prefix_opt->prefix_length;
1743 
1744         if (!ip6_addr_islinklocal(&prefix_addr) && !ip6_addr_isany(&(prefix_opt->prefix))) {
1745           if (prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) {
1746             /* Add to on-link prefix list. */
1747             u32_t valid_life;
1748             s8_t prefix = 0;
1749             valid_life = lwip_htonl(prefix_opt->valid_lifetime);
1750 
1751             /* find cache entry for this prefix. */
1752             if (prefix_opt->prefix_length == 64) {
1753               prefix = nd6_get_onlink_prefix(&prefix_addr, inp);
1754             } else {
1755 #if defined(LWIP_RA_PREFIX_DYNAMIC) && LWIP_RA_PREFIX_DYNAMIC
1756               prefix = nd6_get_onlink_prefix_with_len(&prefix_addr, prefix_len, inp);
1757 #else
1758               LWIP_DEBUGF(IP6_DEBUG, ("on-link prefix length %"U8_F" unrecognized\n",
1759                                       prefix_opt->prefix_length));
1760               valid_life = 0; /* mark negative so that cache entry is not updated */
1761 #endif
1762             }
1763             if (prefix < 0 && valid_life > 0) {
1764               /* Create a new cache entry. */
1765               prefix = nd6_new_onlink_prefix(&prefix_addr, inp);
1766             }
1767             if (prefix >= 0) {
1768               prefix_list[prefix].invalidation_timer = valid_life;
1769               prefix_list[prefix].prefix_len = prefix_len;
1770             }
1771           }
1772 
1773 #if LWIP_IPV6_AUTOCONFIG
1774           if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) {
1775             /* Perform processing for autoconfiguration. */
1776             nd6_process_autoconfig_prefix(inp, prefix_opt, &prefix_addr);
1777           }
1778 #endif /* LWIP_IPV6_AUTOCONFIG */
1779         }
1780 
1781         break;
1782       }
1783       case ND6_OPTION_TYPE_ROUTE_INFO:
1784         /* @todo implement preferred routes.
1785         struct route_option * route_opt;
1786         route_opt = (struct route_option *)buffer;*/
1787 
1788         break;
1789 #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
1790       case ND6_OPTION_TYPE_RDNSS:
1791       {
1792         u8_t num, n;
1793         u16_t copy_offset = offset + SIZEOF_RDNSS_OPTION_BASE;
1794         struct rdnss_option * rdnss_opt;
1795         if (option_len < SIZEOF_RDNSS_OPTION_BASE) {
1796           goto lenerr_drop_free_return;
1797         }
1798 
1799         rdnss_opt = (struct rdnss_option *)buffer;
1800         num = (rdnss_opt->length - 1) / 2;
1801         for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++, copy_offset += sizeof(ip6_addr_p_t)) {
1802           ip_addr_t rdnss_address;
1803 
1804           /* Copy directly from pbuf to get an aligned, zoned copy of the prefix. */
1805           if (pbuf_copy_partial(p, &rdnss_address, sizeof(ip6_addr_p_t), copy_offset) == sizeof(ip6_addr_p_t)) {
1806             IP_SET_TYPE_VAL(rdnss_address, IPADDR_TYPE_V6);
1807             ip6_addr_assign_zone(ip_2_ip6(&rdnss_address), IP6_UNKNOWN, inp);
1808 
1809             if (htonl(rdnss_opt->lifetime) > 0) {
1810               /* TODO implement Lifetime > 0 */
1811               dns_setserver(rdnss_server_idx++, &rdnss_address);
1812             } else {
1813               /* TODO implement DNS removal in dns.c */
1814               u8_t s;
1815               for (s = 0; s < DNS_MAX_SERVERS; s++) {
1816                 const ip_addr_t *addr = dns_getserver(s);
1817                 if(ip_addr_cmp(addr, &rdnss_address)) {
1818                   dns_setserver(s, NULL);
1819                 }
1820               }
1821             }
1822           }
1823         }
1824         break;
1825       }
1826 #endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */
1827       default:
1828         /* Unrecognized option, abort. */
1829         ND6_STATS_INC(nd6.proterr);
1830         break;
1831       }
1832       /* option length is checked earlier to be non-zero to make sure loop ends */
1833       offset += 8 * (u8_t)option_len8;
1834     }
1835 
1836     break; /* ICMP6_TYPE_RA */
1837   }
1838   case ICMP6_TYPE_RD: /* Redirect */
1839   {
1840     struct redirect_header *redir_hdr;
1841     struct lladdr_option *lladdr_opt;
1842     ip6_addr_t tmp;
1843     ip6_addr_t tmp_dest;
1844     ip6_addr_t destination_address, target_address;
1845     u8_t *buffer = NULL; /* Used to copy options. */
1846     u16_t offset;
1847     u8_t dup = 0;
1848 
1849     /* Check that Redir header fits in packet. */
1850     if (p->len < sizeof(struct redirect_header)) {
1851       /* @todo debug message */
1852       pbuf_free(p);
1853       ND6_STATS_INC(nd6.lenerr);
1854       ND6_STATS_INC(nd6.drop);
1855       return;
1856     }
1857 
1858     redir_hdr = (struct redirect_header *)p->payload;
1859 
1860     /* Create an aligned, zoned copy of the destination address. */
1861     ip6_addr_copy_from_packed(destination_address, redir_hdr->destination_address);
1862     ip6_addr_assign_zone(&destination_address, IP6_UNICAST, inp);
1863 
1864     /* Check a subset of the other RFC 4861 Sec. 8.1 requirements. */
1865     if (!ip6_addr_islinklocal(ip6_current_src_addr()) ||
1866         IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM ||
1867         redir_hdr->code != 0 || ip6_addr_ismulticast(&destination_address)) {
1868       pbuf_free(p);
1869       ND6_STATS_INC(nd6.proterr);
1870       ND6_STATS_INC(nd6.drop);
1871       return;
1872     }
1873 
1874     /**
1875     @page RFC-4861 RFC-4861
1876     @par Compliant Section
1877     Section 4.5.  Redirect Message Format
1878     @par Behavior Description
1879     An IP address that is a better first hop to use for the ICMP Destination Address.
1880     When the target is the actual endpoint of communication, i.e., the destination is a neighbor,
1881     the Target Address field MUST contain the same value as the ICMP Destination Address field.
1882     Otherwise, the target is a better first-hop router and the Target Address MUST be the router's
1883     link-local address so that hosts can uniquely identify routers.
1884     Behavior:  Silently discard any received Router Advertisement
1885     */
1886     /**
1887     @page RFC-4861 RFC-4861
1888     @par Compliant Sections
1889     Section 8.1.  Validation of Redirect Messages
1890     @par Behavior Description
1891     The ICMP Target Address is either a link-local address (when redirected to a router) or
1892     the same as the ICMP Destination Address (when redirected to the on-link destination.
1893     Behavior:  Silently discard any received Router Advertisement
1894     */
1895     ip6_addr_copy_from_packed(tmp, redir_hdr->target_address);
1896     ip6_addr_assign_zone(&tmp, IP6_UNICAST, inp);
1897     ip6_addr_copy_from_packed(tmp_dest, redir_hdr->destination_address);
1898     ip6_addr_assign_zone(&tmp_dest, IP6_UNICAST, inp);
1899     if (!ip6_addr_cmp(&(tmp), &(tmp_dest))) {
1900       if (!ip6_addr_islinklocal(&tmp)) {
1901         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1902                     ("ICMPv6 RD header target address is not link local address .\n"));
1903         (void)pbuf_free(p);
1904         ND6_STATS_INC(nd6.proterr);
1905         ND6_STATS_INC(nd6.drop);
1906         return;
1907       }
1908     }
1909 
1910     if (nd6_validate_options((u8_t*)p->payload + sizeof(struct redirect_header),
1911                              (int)(p->len - (sizeof(struct redirect_header)))) < 0) {
1912         pbuf_free(p);
1913         ND6_STATS_INC(nd6.lenerr);
1914         ND6_STATS_INC(nd6.drop);
1915         return;
1916     }
1917 
1918     /* Offset to options. */
1919     offset = sizeof(struct redirect_header);
1920 
1921     /* Process each option. */
1922     while ((p->tot_len - offset) >= 2) {
1923       u16_t option_len;
1924       int opt_type;
1925       int option_len8 = pbuf_try_get_at(p, (u16_t)(offset + 1));
1926       if (option_len8 <= 0) {
1927         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1928                     ("IPv6 options header (optlen %"S32_F") is not specified, packet dropped.\n",
1929                     option_len8));
1930         /* read beyond end or zero length */
1931         goto lenerr_drop_free_return;
1932       }
1933       option_len = (u16_t)(((u8_t)option_len8) << 3);  // multiply by 8 bytes
1934       if (option_len > p->tot_len - offset) {
1935         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1936                     ("IPv6 options header (optlen %"S32_F") does not fit in (total len %"U16_F") \
1937                     and (offset %"U16_F"), packet dropped.\n",
1938                     option_len8, p->tot_len, offset));
1939         /* short packet (option does not fit in) */
1940         goto lenerr_drop_free_return;
1941       }
1942 
1943       opt_type =  pbuf_try_get_at(p, offset);
1944       LWIP_ASSERT("opt_type >= 0", opt_type >= 0);
1945 
1946       switch (opt_type) {
1947         case ND6_OPTION_TYPE_TARGET_LLADDR:
1948           if (option_len != sizeof(struct lladdr_option)) {
1949             LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1950                         ("ND6_OPTION_TYPE_TARGET_LLADDR: (optlen %"U16_F") is less than struct lladdr_option, \
1951                         packet dropped.\n",
1952                          option_len));
1953             goto lenerr_drop_free_return;
1954           }
1955           break;
1956 
1957         case ND6_OPTION_TYPE_REDIRECT_HEADER:
1958           LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING,
1959                       ("ND6_OPTION_TYPE_REDIRECT_HEADER: option not supported so skipping .\n"));
1960           break;
1961 
1962         default:
1963           break;
1964       } /* End of Switch */
1965 
1966       offset = (u16_t)(offset + (u16_t)option_len);
1967     } /* End of While */
1968     /* Codenomicon for ICMPv6 fails due to redirect. */
1969     /* check if target address is not same as stack's address, it will create loopback, treat such RD packet as invalid
1970       packets and ignore thema.
1971     */
1972     ip6_addr_copy_from_packed(tmp, redir_hdr->destination_address);
1973     ip6_addr_assign_zone(&tmp, IP6_UNICAST, inp);
1974     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
1975       if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
1976           ip6_addr_cmp(&tmp, netif_ip6_addr(inp, i))) {
1977           /* Not a valid message. */
1978           pbuf_free(p);
1979           ND6_STATS_INC(nd6.proterr);
1980           ND6_STATS_INC(nd6.drop);
1981           return;
1982       }
1983     }
1984 
1985     /* Copy original destination address to current source address, to have an aligned copy. */
1986     ip6_addr_copy_from_packed(tmp, redir_hdr->destination_address);
1987     ip6_addr_assign_zone(&tmp, IP6_UNICAST, inp);
1988 
1989     /* Find dest address in cache */
1990     dest_idx = nd6_find_destination_cache_entry(&tmp);
1991     if (dest_idx < 0) {
1992       /* Destination not in cache, drop packet. */
1993       pbuf_free(p);
1994       ND6_STATS_INC(nd6.drop);
1995       return;
1996     }
1997     /**
1998     @page RFC-4861 RFC-4861
1999     @par Compliant Sections
2000     Section 8.1. Validation of Redirect Messages
2001     @par Behavior Description
2002     The IP source address of the Redirect is the same as the current first-hop router for the specified
2003      ICMP Destination Address. Behavior:Silently discard any received Router Advertisement
2004     */
2005     if (!ip6_addr_cmp(ip6_current_src_addr(), &(destination_cache[dest_idx].next_hop_addr))) {
2006       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
2007                   ("ICMPv6 RD msg,IP source addr is not same as the dest first-hop/next-hop addr.\n"));
2008       (void)pbuf_free(p);
2009       ND6_STATS_INC(nd6.proterr);
2010       ND6_STATS_INC(nd6.drop);
2011       return;
2012     }
2013     /* Create an aligned, zoned copy of the target address. */
2014     ip6_addr_copy_from_packed(target_address, redir_hdr->target_address);
2015     ip6_addr_assign_zone(&target_address, IP6_UNICAST, inp);
2016 
2017     /* Set the new target address. */
2018     ip6_addr_copy(destination_cache[dest_idx].next_hop_addr, target_address);
2019 
2020     /* Offset to options. */
2021     offset = sizeof(struct redirect_header);
2022 
2023     /* Process each option. */
2024     while ((p->tot_len - offset) >= 2) {
2025       if (p->len == p->tot_len) {
2026         /* no need to copy from contiguous pbuf */
2027         buffer = &((u8_t*)p->payload)[offset];
2028       } else {
2029         buffer = rd6_ra_buffer;
2030         /* already validation is done at the above loop so now just perform buffer parsing */
2031         (void)pbuf_copy_partial(p, buffer, sizeof(struct lladdr_option), offset);
2032       }
2033 
2034       switch (buffer[0]) {
2035         case ND6_OPTION_TYPE_TARGET_LLADDR:
2036           if (dup) {
2037             LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING,
2038                         ("ND6_OPTION_TYPE_TARGET_LLADDR: option is present repeatedly \
2039                          so taking only the first and ignoring the next items \n"));
2040             break;
2041           } else {
2042             dup = 1; /* to avoid updating repeatedly. */
2043           }
2044           lladdr_opt = (struct lladdr_option *)buffer;
2045 
2046           /* If Link-layer address of other router is given, try to add to neighbor cache. */
2047           if (lladdr_opt != NULL) {
2048             i = nd6_find_neighbor_cache_entry(&target_address, inp);
2049             if (i < 0) {
2050               i = nd6_new_neighbor_cache_entry();
2051               if (i >= 0) {
2052                 neighbor_cache[i].netif = inp;
2053                 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
2054                 neighbor_cache[i].lladdrlen = inp->hwaddr_len;
2055                 ip6_addr_copy(neighbor_cache[i].next_hop_address, target_address);
2056 
2057                 /* Receiving a message does not prove reachability: only in one direction.
2058                  * Delay probe in case we get confirmation of reachability from upper layer (TCP). */
2059                 neighbor_cache[i].state = ND6_DELAY;
2060                 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
2061               }
2062             } else {
2063               if (neighbor_cache[i].state == ND6_INCOMPLETE) {
2064                 MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
2065                 neighbor_cache[i].lladdrlen = inp->hwaddr_len;
2066                 /* Receiving a message does not prove reachability: only in one direction.
2067                  * Delay probe in case we get confirmation of reachability from upper layer (TCP). */
2068                 neighbor_cache[i].state = ND6_DELAY;
2069                 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
2070               } else if (neighbor_cache[i].state > ND6_INCOMPLETE) {
2071                 if (!lwip_lladdr_cmp(neighbor_cache[i].lladdr, lladdr_opt->addr, neighbor_cache[i].lladdrlen)) {
2072                   (void)memcpy(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len);
2073                   neighbor_cache[i].lladdrlen = inp->hwaddr_len;
2074                   neighbor_cache[i].state = ND6_STALE;
2075                   neighbor_cache[i].counter.stale_time = 0;
2076                 }
2077               }
2078             }
2079           }
2080           break; /* ND6_OPTION_TYPE_TARGET_LLADDR */
2081 
2082         case ND6_OPTION_TYPE_REDIRECT_HEADER:
2083           LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING,
2084                       ("ND6_OPTION_TYPE_REDIRECT_HEADER: option not supported so skipping .\n"));
2085           break;
2086 
2087         default:
2088           break;
2089       } /* End of Switch */
2090       offset = (u16_t)(offset + (u16_t)(((u16_t)buffer[1]) << 3));
2091     } /* End of While */
2092     break;
2093   }
2094   case ICMP6_TYPE_PTB: /* Packet too big */
2095   {
2096     struct icmpv6_hdr *icmp6hdr; /* Packet too big message */
2097     struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */
2098     u32_t pmtu;
2099     ip6_addr_t destination_address;
2100 
2101     /* Check that ICMPv6 header + IPv6 header fit in payload */
2102     if (p->len < (sizeof(struct icmpv6_hdr) + IP6_HLEN)) {
2103       /* drop short packets */
2104       pbuf_free(p);
2105       ND6_STATS_INC(nd6.lenerr);
2106       ND6_STATS_INC(nd6.drop);
2107       return;
2108     }
2109 
2110     icmp6hdr = (struct icmpv6_hdr *)p->payload;
2111     ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmpv6_hdr));
2112 
2113     /* Create an aligned, zoned copy of the destination address. */
2114     ip6_addr_copy_from_packed(destination_address, ip6hdr->dest);
2115     ip6_addr_assign_zone(&destination_address, IP6_UNKNOWN, inp);
2116 
2117     /* Look for entry in destination cache. */
2118     dest_idx = nd6_find_destination_cache_entry(&destination_address);
2119     if (dest_idx < 0) {
2120       /* Destination not in cache, drop packet. */
2121       pbuf_free(p);
2122       return;
2123     }
2124 
2125     /* Change the Path MTU. */
2126     pmtu = lwip_htonl(icmp6hdr->data);
2127     if (pmtu < NETIF_MTU_MIN) {
2128       destination_cache[dest_idx].pmtu = NETIF_MTU_MIN;
2129     } else {
2130       destination_cache[dest_idx].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF);
2131     }
2132 
2133     break; /* ICMP6_TYPE_PTB */
2134   }
2135 
2136   default:
2137     ND6_STATS_INC(nd6.proterr);
2138     ND6_STATS_INC(nd6.drop);
2139     break; /* default */
2140   }
2141 
2142   pbuf_free(p);
2143   return;
2144 lenerr_drop_free_return:
2145   ND6_STATS_INC(nd6.lenerr);
2146   ND6_STATS_INC(nd6.drop);
2147   pbuf_free(p);
2148 }
2149 
2150 #if (LWIP_RIPPLE && LWIP_CONF_UPDATE_BEACON_PRIORITY)
2151 extern void rpl_core_route_table_entry_cnt(uint16_t *const cnt_max, uint16_t *const cnt_inuse);
2152 
2153 static void
beacon_priority_set(u8_t prio)2154 beacon_priority_set(u8_t prio)
2155 {
2156   struct netif *netif = NULL;
2157 
2158   for (netif = netif_list; netif != NULL; netif = netif->next) {
2159     if (netif->flags & NETIF_FLAG_LOOPBACK) {
2160       continue;
2161     }
2162     (void)netif_set_beacon_prio(netif, prio);
2163   }
2164 }
2165 
2166 void
beacon_priority_update(u8_t is_clear)2167 beacon_priority_update(u8_t is_clear)
2168 {
2169   static u8_t prio_old = NETIF_BEACON_PRIORITY_MAX;
2170   static u8_t netif_cnt_old = 0;
2171   u8_t netif_cnt;
2172   u8_t prio_new;
2173   u8_t parent_cnt;
2174   u16_t nbr_remaining, route_inuse, route_total;
2175 
2176   if (is_clear != 0) {
2177     LWIP_DEBUGF_LOG0(IP6_DEBUG, "bp clr\n");
2178     prio_old = NETIF_BEACON_PRIORITY_MAX;
2179     netif_cnt_old = 0;
2180     beacon_priority_set(0);
2181     return;
2182   }
2183 
2184   if (lwip_is_rpl_running() == lwIP_FALSE) {
2185     LWIP_DEBUGF_LOG0(IP6_DEBUG, "bp n rpl\n");
2186     prio_old = NETIF_BEACON_PRIORITY_MAX;
2187     netif_cnt_old = 0;
2188     return;
2189   }
2190 
2191   parent_cnt = lwip_rpl_dag_parent_count();
2192   if (parent_cnt == 0) {
2193     prio_new = 0;
2194   } else {
2195     nbr_remaining = lwip_nbr_cache_free_count();
2196     rpl_core_route_table_entry_cnt(&route_total, &route_inuse);
2197     prio_new = (u8_t)LWIP_MIN((((u32_t)nbr_remaining) * NETIF_BEACON_PRIORITY_MAX) / LWIP_ND6_NUM_NEIGHBORS,
2198                               (((u32_t)(route_total - route_inuse)) * NETIF_BEACON_PRIORITY_MAX) / route_total);
2199   }
2200   /* if a new netif is added, need to set it's priority, no matter the priority changed or not */
2201   netif_cnt = netif_count();
2202   if ((prio_new != prio_old) || (netif_cnt > netif_cnt_old)) {
2203     beacon_priority_set(prio_new);
2204     prio_old = prio_new;
2205     netif_cnt_old = netif_cnt;
2206   }
2207 
2208   return;
2209 }
2210 #endif
2211 
2212 /**
2213  * Periodic timer for Neighbor discovery functions:
2214  *
2215  * - Update neighbor reachability states
2216  * - Update destination cache entries age
2217  * - Update invalidation timers of default routers and on-link prefixes
2218  * - Update lifetimes of our addresses
2219  * - Perform duplicate address detection (DAD) for our addresses
2220  * - Send router solicitations
2221  */
2222 void
nd6_tmr(void)2223 nd6_tmr(void)
2224 {
2225   s8_t i;
2226   struct netif *netif = NULL;
2227 
2228 #if (LWIP_RIPPLE && LWIP_CONF_UPDATE_BEACON_PRIORITY)
2229   beacon_priority_update(0);
2230 #endif
2231 
2232   /* Process neighbor entries. */
2233   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
2234     switch (neighbor_cache[i].state) {
2235       case ND6_INCOMPLETE:
2236         if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) &&
2237             (!neighbor_cache[i].isrouter)) {
2238           /* Retries exceeded. */
2239           nd6_free_neighbor_cache_entry(i);
2240 #if (LWIP_RIPPLE && LWIP_CONF_UPDATE_BEACON_PRIORITY)
2241           beacon_priority_update(0);
2242 #endif
2243         } else {
2244           /* Send a NS for this entry. */
2245           neighbor_cache[i].counter.probes_sent++;
2246           nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST);
2247         }
2248         break;
2249       case ND6_REACHABLE:
2250         /* Send queued packets, if any are left. Should have been sent already. */
2251         if (neighbor_cache[i].q != NULL) {
2252           nd6_send_q(i);
2253         }
2254         if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) {
2255           /* Change to stale state. */
2256 #if LWIP_RIPPLE
2257           if (neighbor_cache[i].isrouter != 0) {
2258             LWIP_DEBUGF(IP6_DEBUG,
2259                         ("Need to do immediate probe for the default router.\n"));
2260             neighbor_cache[i].state = ND6_DELAY;
2261             neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
2262           } else
2263 #endif
2264           {
2265             neighbor_cache[i].state = ND6_STALE;
2266             neighbor_cache[i].counter.stale_time = 0;
2267           }
2268         } else {
2269           neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL;
2270         }
2271         break;
2272       case ND6_STALE:
2273         neighbor_cache[i].counter.stale_time++;
2274         break;
2275       case ND6_DELAY:
2276         if (neighbor_cache[i].counter.delay_time <= 1) {
2277           /* Change to PROBE state. */
2278           neighbor_cache[i].state = ND6_PROBE;
2279           neighbor_cache[i].counter.probes_sent = 0;
2280         } else {
2281           neighbor_cache[i].counter.delay_time--;
2282         }
2283         break;
2284       case ND6_PROBE:
2285         if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) &&
2286             (!neighbor_cache[i].isrouter)) {
2287           /* Retries exceeded. */
2288           nd6_free_neighbor_cache_entry(i);
2289 #if (LWIP_RIPPLE && LWIP_CONF_UPDATE_BEACON_PRIORITY)
2290           beacon_priority_update(0);
2291 #endif
2292         } else {
2293           /* Send a NS for this entry. */
2294           neighbor_cache[i].counter.probes_sent++;
2295           nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0);
2296         }
2297         break;
2298       case ND6_NO_ENTRY:
2299 #if LWIP_ND6_STATIC_NBR
2300       case ND6_PERMANENT:
2301 #endif
2302       default:
2303         /* Do nothing. */
2304         break;
2305     }
2306   }
2307 
2308   /* Process destination entries. */
2309   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
2310     destination_cache[i].age++;
2311 #if LWIP_RIPPLE && LWIP_ND6_DESTINATIONS_OLDTIME
2312     nd6_refresh_destination_cache_by_age(i);
2313 #endif
2314   }
2315 
2316   /* Process router entries. */
2317   for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) {
2318     if (default_router_list[i].neighbor_entry != NULL) {
2319       /* Active entry. */
2320       if (default_router_list[i].invalidation_timer <= ND6_TMR_INTERVAL / 1000) {
2321         /* No more than 1 second remaining. Clear this entry. Also clear any of
2322          * its destination cache entries, as per RFC 4861 Sec. 5.3 and 6.3.5. */
2323         s8_t j;
2324         for (j = 0; j < LWIP_ND6_NUM_DESTINATIONS; j++) {
2325           if (ip6_addr_cmp(&destination_cache[j].next_hop_addr,
2326               &default_router_list[i].neighbor_entry->next_hop_address)) {
2327             ip6_addr_set_any(&destination_cache[j].destination_addr);
2328           }
2329         }
2330         default_router_list[i].neighbor_entry->isrouter = 0;
2331         default_router_list[i].neighbor_entry = NULL;
2332         default_router_list[i].invalidation_timer = 0;
2333         default_router_list[i].flags = 0;
2334       } else {
2335         default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
2336       }
2337     }
2338   }
2339 
2340   /* Process prefix entries. */
2341   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
2342     if (prefix_list[i].netif != NULL) {
2343       if (prefix_list[i].invalidation_timer <= ND6_TMR_INTERVAL / 1000) {
2344         /* Entry timed out, remove it */
2345         prefix_list[i].invalidation_timer = 0;
2346         prefix_list[i].netif = NULL;
2347       } else {
2348         prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
2349       }
2350     }
2351   }
2352 
2353   /* Process our own addresses, updating address lifetimes and/or DAD state. */
2354   NETIF_FOREACH(netif) {
2355     if (netif->flags & NETIF_FLAG_LOOPBACK) {
2356       continue;
2357     }
2358 
2359     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
2360       u8_t addr_state;
2361 #if LWIP_IPV6_ADDRESS_LIFETIMES
2362       /* Step 1: update address lifetimes (valid and preferred). */
2363       addr_state = netif_ip6_addr_state(netif, i);
2364       /* RFC 4862 is not entirely clear as to whether address lifetimes affect
2365        * tentative addresses, and is even less clear as to what should happen
2366        * with duplicate addresses. We choose to track and update lifetimes for
2367        * both those types, although for different reasons:
2368        * - for tentative addresses, the line of thought of Sec. 5.7 combined
2369        *   with the potentially long period that an address may be in tentative
2370        *   state (due to the interface being down) suggests that lifetimes
2371        *   should be independent of external factors which would include DAD;
2372        * - for duplicate addresses, retiring them early could result in a new
2373        *   but unwanted attempt at marking them as valid, while retiring them
2374        *   late/never could clog up address slots on the netif.
2375        * As a result, we may end up expiring addresses of either type here.
2376        */
2377       if (!ip6_addr_isinvalid(addr_state) &&
2378           !netif_ip6_addr_isstatic(netif, i)) {
2379         u32_t life = netif_ip6_addr_valid_life(netif, i);
2380         if (life <= ND6_TMR_INTERVAL / 1000) {
2381           /* The address has expired. */
2382           netif_ip6_addr_set_valid_life(netif, i, 0);
2383           netif_ip6_addr_set_pref_life(netif, i, 0);
2384           netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
2385         } else {
2386           if (!ip6_addr_life_isinfinite(life)) {
2387             life -= ND6_TMR_INTERVAL / 1000;
2388             LWIP_ASSERT("bad valid lifetime", life != IP6_ADDR_LIFE_STATIC);
2389             netif_ip6_addr_set_valid_life(netif, i, life);
2390           }
2391           /* The address is still here. Update the preferred lifetime too. */
2392           life = netif_ip6_addr_pref_life(netif, i);
2393           if (life <= ND6_TMR_INTERVAL / 1000) {
2394             /* This case must also trigger if 'life' was already zero, so as to
2395              * deal correctly with advertised preferred-lifetime reductions. */
2396             netif_ip6_addr_set_pref_life(netif, i, 0);
2397             if (addr_state == IP6_ADDR_PREFERRED)
2398               netif_ip6_addr_set_state(netif, i, IP6_ADDR_DEPRECATED);
2399           } else if (!ip6_addr_life_isinfinite(life)) {
2400             life -= ND6_TMR_INTERVAL / 1000;
2401             netif_ip6_addr_set_pref_life(netif, i, life);
2402           }
2403         }
2404       }
2405       /* The address state may now have changed, so reobtain it next. */
2406 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
2407       /* Step 2: update DAD state. */
2408       addr_state = netif_ip6_addr_state(netif, i);
2409       if (ip6_addr_istentative(addr_state)) {
2410 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
2411         if (!LWIP_IS_DAD_ENABLED(netif)) {
2412           netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
2413           continue;
2414         }
2415 
2416         if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) {
2417           /* No NA received in response. Mark address as valid. For dynamic
2418            * addresses with an expired preferred lifetime, the state is set to
2419            * deprecated right away. That should almost never happen, though. */
2420           addr_state = IP6_ADDR_PREFERRED;
2421 #if LWIP_IPV6_ADDRESS_LIFETIMES
2422           if (!netif_ip6_addr_isstatic(netif, i) &&
2423               (netif_ip6_addr_pref_life(netif, i) == 0)) {
2424             addr_state = IP6_ADDR_DEPRECATED;
2425           }
2426 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
2427           netif_ip6_addr_set_state(netif, i, addr_state);
2428         } else if (netif_is_up(netif) && netif_is_link_up(netif)) {
2429           /* tentative: set next state by increasing by one */
2430           netif_ip6_addr_set_state(netif, i, addr_state + 1);
2431           /* Send a NS for this address. Use the unspecified address as source
2432            * address in all cases (RFC 4862 Sec. 5.4.2), not in the least
2433            * because as it is, we only consider multicast replies for DAD. */
2434           nd6_send_ns(netif, netif_ip6_addr(netif, i),
2435                       ND6_SEND_FLAG_MULTICAST_DEST | ND6_SEND_FLAG_ANY_SRC);
2436 #if LWIP_RIPPLE && LWIP_ND6_DESTINATIONS_OLDTIME
2437           if (!ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
2438             nd6_refresh_destination_cache(netif_ip6_addr(netif, i));
2439           }
2440 #endif
2441         }
2442 #else
2443         netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
2444 #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
2445       }
2446     }
2447   }
2448 
2449 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
2450   /* Send router solicitation messages, if necessary. */
2451   if (!nd6_tmr_rs_reduction) {
2452     nd6_tmr_rs_reduction = (ND6_RTR_SOLICITATION_INTERVAL / ND6_TMR_INTERVAL) - 1;
2453     NETIF_FOREACH(netif) {
2454       /* Do not send NS/NA/RS/RA packets to loopback interface */
2455       if (netif->flags & NETIF_FLAG_LOOPBACK) {
2456         continue;
2457       }
2458       if ((netif->rs_count > 0) && netif_is_up(netif) &&
2459           netif_is_link_up(netif) &&
2460           !ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)) &&
2461           !ip6_addr_isduplicated(netif_ip6_addr_state(netif, 0))) {
2462         if (nd6_send_rs(netif) == ERR_OK) {
2463           netif->rs_count--;
2464         }
2465       }
2466     }
2467   } else {
2468     nd6_tmr_rs_reduction--;
2469   }
2470 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
2471 
2472 #if LWIP_ND6_ROUTER
2473   for (netif = netif_list; netif != NULL; netif = netif->next) {
2474     /* Do not send NS/NA/RS/RA packets to loopback interface */
2475     if ((netif->flags & NETIF_FLAG_LOOPBACK) != 0) {
2476       continue;
2477     }
2478 
2479     if ((netif->ra_enable != lwIP_TRUE) || !(netif->flags & NETIF_FLAG_UP) ||
2480         (ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) {
2481       continue;
2482     }
2483 
2484     if (netif->ra_init_cnt > 0) {
2485       if (netif->ra_timer > 0) {
2486         netif->ra_timer--;
2487       } else {
2488         netif->ra_init_cnt--;
2489         netif->ra_timer = (netif->ra_init_cnt > 0) ? ND6_RA_INIT_INTERVAL : ND6_RA_NORMAL_INTERVAL;
2490         (void)nd6_send_ra(netif, NULL, 0);
2491       }
2492     } else {
2493       if (netif->ra_timer > 0) {
2494         netif->ra_timer--;
2495       } else {
2496         netif->ra_timer = ND6_RA_NORMAL_INTERVAL;
2497         (void)nd6_send_ra(netif, NULL, 0);
2498       }
2499     }
2500   }
2501 #endif
2502 
2503 #if LWIP_ICMP6_ERR_RT_LMT
2504   icmp6_err_rate_calc();
2505 #endif /* LWIP_ICMP6_ERR_RT_LMT */
2506 }
2507 
2508 #if LWIP_LOWPOWER
2509 #include "lwip/lowpower.h"
2510 u32_t
nd6_tmr_tick(void)2511 nd6_tmr_tick(void)
2512 {
2513   s8_t i;
2514   struct netif *netif = NULL;
2515   u32_t tick = 0;
2516   u32_t val = 0;
2517 
2518   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
2519     switch (neighbor_cache[i].state) {
2520       case ND6_PROBE:
2521       case ND6_INCOMPLETE: /* state PROBE and INCOMPLETE return 1 */
2522         return 1;
2523       case ND6_REACHABLE:
2524         /* Send queued packets, if any are left. Should have been sent already. */
2525         if (neighbor_cache[i].q != NULL) {
2526           return 1;
2527         }
2528         if (neighbor_cache[i].counter.reachable_time >= ND6_TMR_INTERVAL) {
2529           val = neighbor_cache[i].counter.reachable_time / ND6_TMR_INTERVAL;
2530           SET_TMR_TICK(tick, val);
2531         }
2532         break;
2533       case ND6_DELAY:
2534         val = neighbor_cache[i].counter.delay_time;
2535         SET_TMR_TICK(tick, val);
2536         break;
2537       default:
2538         /* Do nothing. */
2539         break;
2540     }
2541   }
2542 
2543   /* Process router entries. */
2544   for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) {
2545     if (default_router_list[i].neighbor_entry != NULL) {
2546       val = default_router_list[i].invalidation_timer;
2547       SET_TMR_TICK(tick, val);
2548     }
2549   }
2550 
2551   /* Process prefix entries. */
2552   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
2553     if (prefix_list[i].netif != NULL) {
2554       val = prefix_list[i].invalidation_timer;
2555       SET_TMR_TICK(tick, val);
2556     }
2557   }
2558 
2559   /* Process our own addresses, updating address lifetimes and/or DAD state. */
2560   NETIF_FOREACH(netif) {
2561     if ((netif->flags & NETIF_FLAG_LOOPBACK) != 0) {
2562       continue;
2563     }
2564     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
2565       u8_t addr_state;
2566 #if LWIP_IPV6_ADDRESS_LIFETIMES
2567       /* Step 1: update address lifetimes (valid and preferred). */
2568       addr_state = netif_ip6_addr_state(netif, i);
2569       if (!ip6_addr_isinvalid(addr_state) &&
2570           !netif_ip6_addr_isstatic(netif, i)) {
2571         u32_t life = netif_ip6_addr_valid_life(netif, i);
2572         if (!ip6_addr_life_isinfinite(life)) {
2573           SET_TMR_TICK(tick, life);
2574         }
2575 
2576         life = netif_ip6_addr_pref_life(netif, i);
2577         if (!ip6_addr_life_isinfinite(life)) {
2578           SET_TMR_TICK(tick, life);
2579         }
2580       }
2581       /* The address state may now have changed, so reobtain it next. */
2582 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
2583       /* Step 2: update DAD state. */
2584       addr_state = netif_ip6_addr_state(netif, i);
2585       if (ip6_addr_istentative(addr_state)) {
2586         LOWPOWER_DEBUG(("%s tmr tick: 1\n", __func__));
2587         return 1;
2588       }
2589     }
2590   }
2591 
2592   /* Router solicitations are sent in 4 second intervals (see RFC 4861, ch. 6.3.7) */
2593   /* ND6_RTR_SOLICITATION_INTERVAL */
2594 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
2595   if (nd6_tmr_rs_reduction > 0) {
2596     val = nd6_tmr_rs_reduction;
2597     SET_TMR_TICK(tick, val);
2598   }
2599 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
2600 
2601 #if LWIP_ND6_ROUTER
2602   for (netif = netif_list; netif != NULL; netif = netif->next) {
2603     /* Do not send NS/NA/RS/RA packets to loopback interface */
2604     if ((netif->flags & NETIF_FLAG_LOOPBACK) != 0) {
2605       continue;
2606     }
2607 
2608     if ((netif->ra_enable != lwIP_TRUE) || ((netif->flags & NETIF_FLAG_UP) == 0) ||
2609         (ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) {
2610       continue;
2611     }
2612     val = netif->ra_timer;
2613     SET_TMR_TICK(tick, val);
2614   }
2615 #endif
2616 
2617   LOWPOWER_DEBUG(("%s tmr tick: %u\n", __func__, tick));
2618   return tick;
2619 }
2620 #endif /* LWIP_LOWPOWER */
2621 
2622 /** Send a neighbor solicitation message for a specific neighbor cache entry
2623  *
2624  * @param entry the neightbor cache entry for wich to send the message
2625  * @param flags one of ND6_SEND_FLAG_*
2626  */
2627 static void
nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry * entry,u8_t flags)2628 nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags)
2629 {
2630   nd6_send_ns(entry->netif, &entry->next_hop_address, flags);
2631 }
2632 
2633 /**
2634  * Send a neighbor solicitation message
2635  *
2636  * @param netif the netif on which to send the message
2637  * @param target_addr the IPv6 target address for the ND message
2638  * @param flags one of ND6_SEND_FLAG_*
2639  */
2640 static void
nd6_send_ns(struct netif * netif,const ip6_addr_t * target_addr,u8_t flags)2641 nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags)
2642 {
2643   struct ns_header *ns_hdr = NULL;
2644   struct pbuf *p = NULL;
2645   const ip6_addr_t *src_addr = NULL;
2646   u16_t lladdr_opt_len;
2647 
2648   /*
2649    * RFC4862 section 7.7.2: If the source address of the packet prompting the solicitation is the same
2650    * as one of the addresses assigned to the outgoing interface, that address SHOULD be placed in the IP
2651    * Source Address of the outgoing solicitation. Otherwise, any one of the addresses assigned to the
2652    * interface should be used. Using the prompting packet's source address when possible ensures that
2653    * the recipient of the Neighbor Solicitation installs in its Neighbor Cache the IP address that is highly
2654    * likely to be used in subsequent return traffic belonging to the prompting packet's "connection".
2655    */
2656   /*
2657    * lwip does NOT comply with this specification as the source address of NA is choosen based on the
2658    * target address. In most of cases, if users don't declare the specific source address by binding socket to
2659    * one specific address, the source address of IPV6 packets is also choosen based on target address, so the
2660    * source address of NS is same as the prompting IPv6 packet.
2661    */
2662   if (!(flags & ND6_SEND_FLAG_ANY_SRC)) {
2663     src_addr = ip_2_ip6(ip6_select_source_address(netif, target_addr));
2664     if (src_addr == NULL) {
2665       int i;
2666       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
2667         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
2668               ip6_addr_netcmp(target_addr, netif_ip6_addr(netif, i))) {
2669           src_addr = netif_ip6_addr(netif, i);
2670           break;
2671         }
2672       }
2673 
2674       if (i == LWIP_IPV6_NUM_ADDRESSES) {
2675         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NS: no available src address\n"));
2676         ND6_STATS_INC(nd6.err);
2677         return;
2678       }
2679     }
2680     /* calculate option length (in 8-byte-blocks) */
2681     lladdr_opt_len = (u16_t)(((netif->hwaddr_len + 2) + 7) >> 3);
2682   } else {
2683     src_addr = IP6_ADDR_ANY6;
2684     /* Option "MUST NOT be included when the source IP address is the unspecified address." */
2685     lladdr_opt_len = 0;
2686   }
2687 
2688   /* Allocate a packet. */
2689   p = pbuf_alloc(PBUF_IP, (u16_t)(sizeof(struct ns_header) + (unsigned int)(lladdr_opt_len << 3)), PBUF_RAM);
2690   if (p == NULL) {
2691     ND6_STATS_INC(nd6.memerr);
2692     return;
2693   }
2694 
2695   /* Set fields. */
2696   ns_hdr = (struct ns_header *)p->payload;
2697 
2698   ns_hdr->type = ICMP6_TYPE_NS;
2699   ns_hdr->code = 0;
2700   ns_hdr->chksum = 0;
2701   ns_hdr->reserved = 0;
2702   ip6_addr_copy_to_packed(ns_hdr->target_address, *target_addr);
2703 
2704   if (lladdr_opt_len != 0) {
2705     struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header));
2706     lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR;
2707     lladdr_opt->length = (u8_t)lladdr_opt_len;
2708     SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len);
2709   }
2710 
2711   /* Generate the solicited node address for the target address. */
2712   if (flags & ND6_SEND_FLAG_MULTICAST_DEST) {
2713     ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]);
2714     ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST, netif);
2715     target_addr = &multicast_address;
2716   }
2717 
2718 #if CHECKSUM_GEN_ICMP6
2719   IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
2720     ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
2721       target_addr);
2722   }
2723 #endif /* CHECKSUM_GEN_ICMP6 */
2724 
2725   /* Send the packet out. */
2726   ND6_STATS_INC(nd6.xmit);
2727   ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr,
2728       ND6_HOPLIM, 0, IP6_NEXTH_ICMP6, netif);
2729   pbuf_free(p);
2730 }
2731 
2732 /**
2733  * Send a neighbor advertisement message
2734  *
2735  * @param netif the netif on which to send the message
2736  * @param target_addr the IPv6 target address for the ND message
2737  * @param flags one of ND6_SEND_FLAG_*
2738  */
2739 void
nd6_send_na(struct netif * netif,const ip6_addr_t * target_addr,u8_t flags)2740 nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags)
2741 {
2742   struct na_header *na_hdr;
2743   struct lladdr_option *lladdr_opt;
2744   struct pbuf *p;
2745   const ip6_addr_t *src_addr;
2746   const ip6_addr_t *dest_addr;
2747   u16_t lladdr_opt_len;
2748 
2749   LWIP_ASSERT("target address is required", target_addr != NULL);
2750 
2751   /* Use link-local address as source address. */
2752   /* src_addr = netif_ip6_addr(netif, 0); */
2753   /* Use target address as source address. */
2754   src_addr = target_addr;
2755 
2756   /* Allocate a packet. */
2757   lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0);
2758   p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + (lladdr_opt_len << 3), PBUF_RAM);
2759   if (p == NULL) {
2760     ND6_STATS_INC(nd6.memerr);
2761     return;
2762   }
2763 
2764   /* Set fields. */
2765   na_hdr = (struct na_header *)p->payload;
2766   lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header));
2767 
2768   na_hdr->type = ICMP6_TYPE_NA;
2769   na_hdr->code = 0;
2770   na_hdr->chksum = 0;
2771   na_hdr->flags = flags & 0xf0;
2772   na_hdr->reserved[0] = 0;
2773   na_hdr->reserved[1] = 0;
2774   na_hdr->reserved[2] = 0;
2775   ip6_addr_copy_to_packed(na_hdr->target_address, *target_addr);
2776 
2777   lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR;
2778   lladdr_opt->length = (u8_t)lladdr_opt_len;
2779   SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len);
2780 
2781   /* Generate the solicited node address for the target address. */
2782   if (flags & ND6_SEND_FLAG_MULTICAST_DEST) {
2783     ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]);
2784     ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST, netif);
2785     dest_addr = &multicast_address;
2786   } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) {
2787     ip6_addr_set_allnodes_linklocal(&multicast_address);
2788     ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST, netif);
2789     dest_addr = &multicast_address;
2790   } else {
2791     dest_addr = ip6_current_src_addr();
2792   }
2793 
2794 #if CHECKSUM_GEN_ICMP6
2795   IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
2796     na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
2797       dest_addr);
2798   }
2799 #endif /* CHECKSUM_GEN_ICMP6 */
2800 
2801   /* Send the packet out. */
2802   ND6_STATS_INC(nd6.xmit);
2803   ip6_output_if(p, src_addr, dest_addr,
2804       ND6_HOPLIM, 0, IP6_NEXTH_ICMP6, netif);
2805   pbuf_free(p);
2806 }
2807 
2808 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
2809 /**
2810  * Send a router solicitation message
2811  *
2812  * @param netif the netif on which to send the message
2813  */
2814 err_t
nd6_send_rs(struct netif * netif)2815 nd6_send_rs(struct netif *netif)
2816 {
2817   struct rs_header *rs_hdr;
2818   struct lladdr_option *lladdr_opt;
2819   struct pbuf *p;
2820   const ip6_addr_t *src_addr;
2821   err_t err;
2822   u16_t lladdr_opt_len = 0;
2823   u16_t lladdr_opt_data_len = 0;
2824 
2825   /* Link-local source address, or unspecified address? */
2826   if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) {
2827     src_addr = netif_ip6_addr(netif, 0);
2828   } else {
2829     src_addr = IP6_ADDR_ANY6;
2830   }
2831 
2832   /* Generate the all routers target address. */
2833   ip6_addr_set_allrouters_linklocal(&multicast_address);
2834   ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST, netif);
2835 
2836   /* Allocate a packet. */
2837   if (src_addr != IP6_ADDR_ANY6) {
2838     lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0);
2839   }
2840   p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM);
2841   if (p == NULL) {
2842     ND6_STATS_INC(nd6.memerr);
2843     return ERR_BUF;
2844   }
2845 
2846   /* Set fields. */
2847   rs_hdr = (struct rs_header *)p->payload;
2848 
2849   rs_hdr->type = ICMP6_TYPE_RS;
2850   rs_hdr->code = 0;
2851   rs_hdr->chksum = 0;
2852   rs_hdr->reserved = 0;
2853 
2854   if (src_addr != IP6_ADDR_ANY6) {
2855     /* Include our hw address. */
2856     lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header));
2857     lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR;
2858     lladdr_opt->length = (u8_t)lladdr_opt_len;
2859     /* the padding bytes must be set to zero */
2860     lladdr_opt_data_len = (lladdr_opt_len << 3) - RS_LLADDR_OPTION_HEADER_LEN;
2861     if (lladdr_opt_data_len > netif->hwaddr_len) {
2862       (void)memset_s(lladdr_opt->addr, lladdr_opt_data_len, 0, lladdr_opt_data_len);
2863     }
2864 
2865     if (memcpy_s(lladdr_opt->addr, lladdr_opt_data_len, netif->hwaddr, netif->hwaddr_len) != EOK) {
2866       (void)pbuf_free(p);
2867       return ERR_MEM;
2868     }
2869   }
2870 
2871 #if CHECKSUM_GEN_ICMP6
2872   IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
2873     rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
2874       &multicast_address);
2875   }
2876 #endif /* CHECKSUM_GEN_ICMP6 */
2877 
2878   /* Send the packet out. */
2879   ND6_STATS_INC(nd6.xmit);
2880 
2881   err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address,
2882       ND6_HOPLIM, 0, IP6_NEXTH_ICMP6, netif);
2883   pbuf_free(p);
2884 
2885   return err;
2886 }
2887 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
2888 
2889 #if LWIP_IPV6 && LWIP_NETIF_NBR_CACHE_API
2890 err_t
nd6_del_neighbor_cache_entry_manually(struct netif * netif,struct ip6_addr * nbrip)2891 nd6_del_neighbor_cache_entry_manually(struct netif *netif, struct ip6_addr *nbrip)
2892 {
2893   int idx;
2894   idx = nd6_find_neighbor_cache_entry(nbrip, netif);
2895   if ((idx >= 0) && (neighbor_cache[idx].netif == netif)) {
2896     /* Check if its the router in that case first remove the router entry and then clear the nbr cache */
2897     if (neighbor_cache[idx].isrouter != 0) {
2898       s8_t router_index;
2899       router_index = nd6_get_router(nbrip, netif);
2900       if ((router_index >= 0) && (default_router_list[router_index].neighbor_entry == &(neighbor_cache[idx]))) {
2901         default_router_list[router_index].neighbor_entry = NULL;
2902         default_router_list[router_index].flags = 0;
2903         neighbor_cache[idx].isrouter = 0;
2904       }
2905     }
2906 
2907     nd6_free_neighbor_cache_entry(idx);
2908 #if (LWIP_RIPPLE && LWIP_CONF_UPDATE_BEACON_PRIORITY)
2909     beacon_priority_update(0);
2910 #endif
2911   } else {
2912     LWIP_DEBUGF(IP6_DEBUG, ("ND6: No NBR found \n"));
2913     return ERR_NBR_NOTFOUND;
2914   }
2915 
2916   return ERR_OK;
2917 }
2918 
2919 err_t
nd6_add_neighbor_cache_entry_manually(struct netif * netif,struct nd6_neighbor_info * nbrinfo)2920 nd6_add_neighbor_cache_entry_manually(struct netif *netif, struct nd6_neighbor_info *nbrinfo)
2921 {
2922   int idx;
2923   idx = nd6_find_neighbor_cache_entry(&(nbrinfo->nbripaddr), netif);
2924   if (idx >= 0) {
2925     /*
2926      * When a neighbor already exist for this node we will not allow to modify
2927      * it unless until its a static neighbor entry
2928      */
2929 #if LWIP_ND6_STATIC_NBR
2930     if ((neighbor_cache[idx].state == ND6_PERMANENT)) {
2931       neighbor_cache[idx].netif = netif;
2932       if (memcpy_s(neighbor_cache[idx].lladdr, NETIF_MAX_HWADDR_LEN, nbrinfo->hwaddr, nbrinfo->hwlen) != EOK) {
2933         ND6_STATS_INC(nd6.memerr);
2934         return ERR_MEM;
2935       }
2936       neighbor_cache[idx].lladdrlen = nbrinfo->hwlen;
2937     } else
2938 #endif
2939     {
2940       LWIP_DEBUGF(IP6_DEBUG, ("ND6: Overwritting non-static entry is forbidden"));
2941       return ERR_NBR_OVERWRITEFORBIDDEN;
2942     }
2943   } else {
2944     idx = nd6_new_neighbor_cache_entry();
2945     if (idx < 0) {
2946       /*
2947        * We couldn't assign a cache entry for this neighbor.
2948        * we won't be able to reply. drop it.
2949        */
2950       ND6_STATS_INC(nd6.cache_full);
2951       return ERR_MEM;
2952     }
2953 
2954     neighbor_cache[idx].netif = netif;
2955     if (memcpy_s(neighbor_cache[idx].lladdr, NETIF_MAX_HWADDR_LEN, nbrinfo->hwaddr, nbrinfo->hwlen) != EOK) {
2956       ND6_STATS_INC(nd6.memerr);
2957       return ERR_MEM;
2958     }
2959     neighbor_cache[idx].lladdrlen = nbrinfo->hwlen;
2960 
2961     ip6_addr_set(&(neighbor_cache[idx].next_hop_address), &(nbrinfo->nbripaddr));
2962 
2963     /*
2964      * Receiving a message does not prove reachability: only in one direction.
2965      * Delay probe in case we get confirmation of reachability from upper layer (TCP).
2966      */
2967     neighbor_cache[idx].state = nbrinfo->curstate;
2968     neighbor_cache[idx].counter.reachable_time = nbrinfo->reachabletime;
2969   }
2970 
2971   return ERR_OK;
2972 }
2973 
2974 err_t
nd6_get_neighbor_cache_info(struct netif * netif,struct ip6_addr * nbrip,struct nd6_neighbor_info * nbrinfo)2975 nd6_get_neighbor_cache_info(struct netif *netif, struct ip6_addr *nbrip,
2976                             struct nd6_neighbor_info *nbrinfo)
2977 {
2978   int idx;
2979   idx = nd6_find_neighbor_cache_entry(nbrip, netif);
2980   if ((idx >= 0) && (neighbor_cache[idx].netif == netif)) {
2981     if (memcpy_s(nbrinfo->hwaddr, NETIF_MAX_HWADDR_LEN, neighbor_cache[idx].lladdr, NETIF_MAX_HWADDR_LEN) != EOK) {
2982       ND6_STATS_INC(nd6.memerr);
2983       return ERR_MEM;
2984     }
2985     nbrinfo->hwlen = neighbor_cache[idx].lladdrlen;
2986     ip6_addr_set(&(nbrinfo->nbripaddr), &(neighbor_cache[idx].next_hop_address));
2987     nbrinfo->curstate = neighbor_cache[idx].state;
2988     /* The rechable time will be same as the user configured */
2989     nbrinfo->reachabletime = reachable_time;
2990 #if LWIP_ND6_STATIC_NBR
2991     /* If its a static entry it will not have any rechablility test so time will be set to 0 */
2992     if (nbrinfo->curstate == ND6_PERMANENT) {
2993       nbrinfo->reachabletime = 0;
2994     }
2995 #endif
2996   } else {
2997     LWIP_DEBUGF(IP6_DEBUG, ("ND6: No NBR found \n"));
2998     return ERR_NBR_NOTFOUND;
2999   }
3000 
3001   return ERR_OK;
3002 }
3003 #endif /* LWIP_IPV6 && LWIP_NETIF_NBR_CACHE_API */
3004 
3005 /**
3006  * Search for a neighbor cache entry
3007  *
3008  * @param ip6addr the IPv6 address of the neighbor
3009  * @return The neighbor cache entry index that matched, -1 if no
3010  * entry is found
3011  */
3012 static s8_t
nd6_find_neighbor_cache_entry(const ip6_addr_t * ip6addr,const struct netif * netif)3013 nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr, const struct netif *netif)
3014 {
3015   s8_t i;
3016   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3017     if ((neighbor_cache[i].netif == netif) &&
3018         (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address)))) {
3019       return i;
3020     }
3021   }
3022   return -1;
3023 }
3024 
3025 #if LWIP_RIPPLE
3026 struct nd6_neighbor_cache_entry *
nd6_get_neighbor_byindex(s8_t nbrindex)3027 nd6_get_neighbor_byindex(s8_t nbrindex)
3028 {
3029   if ((nbrindex < 0) || (nbrindex >= LWIP_ND6_NUM_NEIGHBORS)) {
3030     return NULL;
3031   }
3032 
3033   /* If no neighbor exists at the given index */
3034   if (neighbor_cache[nbrindex].state == ND6_NO_ENTRY) {
3035     return NULL;
3036   }
3037 
3038   return &(neighbor_cache[nbrindex]);
3039 }
3040 
3041 struct nd6_neighbor_cache_entry *
nd6_neighbor_cache_lookup(const ip6_addr_t * ip6addr,struct netif * iface)3042 nd6_neighbor_cache_lookup(const ip6_addr_t *ip6addr, struct netif *iface)
3043 {
3044   s8_t i;
3045   if ((ip6addr == NULL) || (iface == NULL)) {
3046     return NULL;
3047   }
3048   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3049     if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address)) && (neighbor_cache[i].netif == iface)) {
3050       return &(neighbor_cache[i]);
3051     }
3052   }
3053 
3054   return NULL;
3055 }
3056 #endif /* LWIP_RIPPLE */
3057 
3058 #if LWIP_ENABLE_ROUTER && LWIP_RIPPLE
3059 void
nd6_remove_neighbor_cache_entry(struct netif * netif,const ip6_addr_t * nbr_addr)3060 nd6_remove_neighbor_cache_entry(struct netif *netif,
3061                                 const ip6_addr_t *nbr_addr)
3062 {
3063   s8_t index;
3064 
3065   index = nd6_find_neighbor_cache_entry(nbr_addr, netif);
3066   if (index >= 0) {
3067     nd6_free_neighbor_cache_entry(index);
3068   }
3069 }
3070 
3071 void
nd6_remove_neighbor_by_mac(struct netif * netif,const u8_t * mac,u8_t maclen)3072 nd6_remove_neighbor_by_mac(struct netif *netif, const u8_t *mac, u8_t maclen)
3073 {
3074   s8_t i;
3075   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3076     if ((neighbor_cache[i].netif == netif) && (maclen == neighbor_cache[i].lladdrlen) &&
3077         (memcmp(mac, neighbor_cache[i].lladdr, maclen) == 0)) {
3078       nd6_free_neighbor_cache_entry(i);
3079     }
3080   }
3081 #if (LWIP_RIPPLE && LWIP_CONF_UPDATE_BEACON_PRIORITY)
3082   beacon_priority_update(0);
3083 #endif
3084 }
3085 
3086 #endif /* LWIP_ENABLE_ROUTER && LWIP_RIPPLE */
3087 
3088 /**
3089  * Create a new neighbor cache entry.
3090  *
3091  * If no unused entry is found, will try to recycle an old entry
3092  * according to ad-hoc "age" heuristic.
3093  *
3094  * @return The neighbor cache entry index that was created, -1 if no
3095  * entry could be created
3096  */
3097 static s8_t
nd6_new_neighbor_cache_entry(void)3098 nd6_new_neighbor_cache_entry(void)
3099 {
3100   s8_t i;
3101   s8_t j;
3102   u32_t time;
3103 
3104   /* First, try to find an empty entry. */
3105   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3106     if (neighbor_cache[i].state == ND6_NO_ENTRY) {
3107       return i;
3108     }
3109   }
3110 
3111   /* We need to recycle an entry. in general, do not recycle if it is a router. */
3112 
3113   /* Next, try to find a Stale entry. */
3114   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3115     if ((neighbor_cache[i].state == ND6_STALE) &&
3116         (!neighbor_cache[i].isrouter)) {
3117       nd6_free_neighbor_cache_entry(i);
3118       return i;
3119     }
3120   }
3121 
3122   /* Next, try to find a Probe entry. */
3123   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3124     if ((neighbor_cache[i].state == ND6_PROBE) &&
3125         (!neighbor_cache[i].isrouter)) {
3126       nd6_free_neighbor_cache_entry(i);
3127       return i;
3128     }
3129   }
3130 
3131   /* Next, try to find a Delayed entry. */
3132   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3133     if ((neighbor_cache[i].state == ND6_DELAY) &&
3134         (!neighbor_cache[i].isrouter)) {
3135       nd6_free_neighbor_cache_entry(i);
3136       return i;
3137     }
3138   }
3139 
3140   /* Next, try to find the oldest reachable entry. */
3141   time = 0xfffffffful;
3142   j = -1;
3143   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3144     if ((neighbor_cache[i].state == ND6_REACHABLE) &&
3145         (!neighbor_cache[i].isrouter)) {
3146       if (neighbor_cache[i].counter.reachable_time < time) {
3147         j = i;
3148         time = neighbor_cache[i].counter.reachable_time;
3149       }
3150     }
3151   }
3152   if (j >= 0) {
3153     nd6_free_neighbor_cache_entry(j);
3154     return j;
3155   }
3156 
3157   /* Next, find oldest incomplete entry without queued packets. */
3158   time = 0;
3159   j = -1;
3160   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3161     if (
3162         (neighbor_cache[i].q == NULL) &&
3163         (neighbor_cache[i].state == ND6_INCOMPLETE) &&
3164         (!neighbor_cache[i].isrouter)) {
3165       if (neighbor_cache[i].counter.probes_sent >= time) {
3166         j = i;
3167         time = neighbor_cache[i].counter.probes_sent;
3168       }
3169     }
3170   }
3171   if (j >= 0) {
3172     nd6_free_neighbor_cache_entry(j);
3173     return j;
3174   }
3175 
3176   /* Next, find oldest incomplete entry with queued packets. */
3177   time = 0;
3178   j = -1;
3179   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
3180     if ((neighbor_cache[i].state == ND6_INCOMPLETE) &&
3181         (!neighbor_cache[i].isrouter)) {
3182       if (neighbor_cache[i].counter.probes_sent >= time) {
3183         j = i;
3184         time = neighbor_cache[i].counter.probes_sent;
3185       }
3186     }
3187   }
3188   if (j >= 0) {
3189     nd6_free_neighbor_cache_entry(j);
3190     return j;
3191   }
3192 
3193   /* No more entries to try. */
3194   return -1;
3195 }
3196 
3197 /**
3198  * Will free any resources associated with a neighbor cache
3199  * entry, and will mark it as unused.
3200  *
3201  * @param i the neighbor cache entry index to free
3202  */
3203 static void
nd6_free_neighbor_cache_entry(s8_t i)3204 nd6_free_neighbor_cache_entry(s8_t i)
3205 {
3206   struct nd6_neighbor_cache_entry entry;
3207 
3208   if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) {
3209     return;
3210   }
3211 
3212 #if !LWIP_RIPPLE
3213   if (neighbor_cache[i].isrouter) {
3214     /* isrouter needs to be cleared before deleting a neighbor cache entry */
3215     return;
3216   }
3217 #endif
3218 
3219 #if LWIP_RIPPLE && LWIP_ND6_ROUTER
3220   if ((neighbor_cache[i].isrouter != 0) && (neighbor_cache[i].netif != NULL) &&
3221       (neighbor_cache[i].netif->forwarding == 0)) {
3222     /* isrouter needs to be cleared before deleting a neighbor cache entry */
3223     return;
3224   }
3225 #endif
3226 
3227   /* Free any queued packets. */
3228   if (neighbor_cache[i].q != NULL) {
3229     nd6_free_q(neighbor_cache[i].q);
3230     neighbor_cache[i].q = NULL;
3231   }
3232 
3233   entry = neighbor_cache[i];
3234   neighbor_cache[i].state = ND6_NO_ENTRY;
3235   neighbor_cache[i].isrouter = 0;
3236   neighbor_cache[i].netif = NULL;
3237   /* set the lladdr to 0, for removing the entry by mac */
3238   neighbor_cache[i].lladdrlen = 0;
3239   (void)memset_s(neighbor_cache[i].lladdr, NETIF_MAX_HWADDR_LEN, 0, NETIF_MAX_HWADDR_LEN);
3240   neighbor_cache[i].counter.reachable_time = 0;
3241   ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address));
3242 
3243 #if LWIP_RIPPLE
3244   /* Indicate the RPL Layer that this neighbor is getting removed */
3245   LWIP_CONF_ND6_NEIGHBOR_STATE_CHANGED(&entry);
3246 
3247   /* Clean the Destination cache */
3248   nd6_refresh_destination_cache(&(entry.next_hop_address));
3249 #else
3250   (void)entry;
3251 #endif
3252 }
3253 
3254 /**
3255  * Search for a destination cache entry
3256  *
3257  * @param ip6addr the IPv6 address of the destination
3258  * @return The destination cache entry index that matched, -1 if no
3259  * entry is found
3260  */
3261 static s16_t
nd6_find_destination_cache_entry(const ip6_addr_t * ip6addr)3262 nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr)
3263 {
3264   s16_t i;
3265 
3266   IP6_ADDR_ZONECHECK(ip6addr);
3267 
3268   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
3269     if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) {
3270       return i;
3271     }
3272   }
3273   return -1;
3274 }
3275 
3276 /**
3277  * Create a new destination cache entry. If no unused entry is found,
3278  * will recycle oldest entry.
3279  *
3280  * @return The destination cache entry index that was created, -1 if no
3281  * entry was created
3282  */
3283 static s16_t
nd6_new_destination_cache_entry(void)3284 nd6_new_destination_cache_entry(void)
3285 {
3286   s16_t i, j;
3287   u32_t age;
3288 
3289   /* Find an empty entry. */
3290   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
3291     if (ip6_addr_isany(&(destination_cache[i].destination_addr))) {
3292       return i;
3293     }
3294   }
3295 
3296   /* Find oldest entry. */
3297   age = 0;
3298   j = LWIP_ND6_NUM_DESTINATIONS - 1;
3299   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
3300     if (destination_cache[i].age > age) {
3301       j = i;
3302     }
3303   }
3304 
3305   return j;
3306 }
3307 
3308 /**
3309  * Clear the destination cache.
3310  *
3311  * This operation may be necessary for consistency in the light of changing
3312  * local addresses and/or use of the gateway hook.
3313  */
3314 void
nd6_clear_destination_cache(void)3315 nd6_clear_destination_cache(void)
3316 {
3317   int i;
3318 
3319   for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) {
3320     ip6_addr_set_any(&destination_cache[i].destination_addr);
3321   }
3322 }
3323 
3324 #if !LWIP_RIPPLE || LWIP_ND6_ROUTER
3325 /**
3326  * Determine whether an address matches an on-link prefix or the subnet of a
3327  * statically assigned address.
3328  *
3329  * @param ip6addr the IPv6 address to match
3330  * @return 1 if the address is on-link, 0 otherwise
3331  */
3332 static int
nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr,struct netif * netif)3333 nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif)
3334 {
3335   s8_t i;
3336 
3337   /* Check to see if the address matches an on-link prefix. */
3338   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
3339     if ((prefix_list[i].netif == netif) &&
3340         (prefix_list[i].invalidation_timer > 0) &&
3341         ip6_addr_prefix_netcmp(ip6addr, &(prefix_list[i].prefix), (prefix_list[i].prefix_len >> 3))) {
3342       return 1;
3343     }
3344   }
3345 
3346 #if !LWIP_RIPPLE
3347   /* Check to see if address prefix matches a manually configured (= static)
3348    * address. Static addresses have an implied /64 subnet assignment. Dynamic
3349    * addresses (from autoconfiguration) have no implied subnet assignment, and
3350    * are thus effectively /128 assignments. See RFC 5942 for more on this. */
3351   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
3352     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
3353         ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) {
3354       return 1;
3355     }
3356   }
3357 #endif
3358   return 0;
3359 }
3360 #endif
3361 
3362 /**
3363  * get  an adressing matching prefix on netif
3364  *
3365  * @param ip6addr the IPv6 address to match
3366  * @return 1 if the address is on-link, 0 otherwise
3367  */
3368 const ip6_addr_t *
nd6_get_prefix_addr(const ip6_addr_t * ip6addr,const struct netif * netif)3369 nd6_get_prefix_addr(const ip6_addr_t *ip6addr, const struct netif *netif)
3370 {
3371   if ((ip6addr == NULL) || (netif == NULL)) {
3372     return NULL;
3373   }
3374   s8_t i;
3375   /* Check to see if address prefix matches a (manually?) configured address. */
3376   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
3377     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
3378         ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) {
3379       return netif_ip6_addr(netif, i);
3380     }
3381   }
3382   return NULL;
3383 }
3384 
3385 /**
3386  * Select a default router for a destination.
3387  *
3388  * This function is used both for routing and for finding a next-hop target for
3389  * a packet. In the former case, the given netif is NULL, and the returned
3390  * router entry must be for a netif suitable for sending packets (up, link up).
3391  * In the latter case, the given netif is not NULL and restricts router choice.
3392  *
3393  * @param ip6addr the destination address
3394  * @param netif the netif for the outgoing packet, if known
3395  * @return the default router entry index, or -1 if no suitable
3396  *         router is found
3397  */
3398 static s8_t
nd6_select_router(const ip6_addr_t * ip6addr,struct netif * netif)3399 nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif)
3400 {
3401   struct netif *router_netif;
3402   s8_t i, j, valid_router;
3403   static s8_t last_router;
3404 
3405   LWIP_UNUSED_ARG(ip6addr); /* @todo match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */
3406 
3407   /* @todo: implement default router preference */
3408 
3409   /* Look for valid routers. A reachable router is preferred. */
3410   valid_router = -1;
3411   for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) {
3412     /* Is the router netif both set and apppropriate? */
3413     if (default_router_list[i].neighbor_entry != NULL) {
3414       router_netif = default_router_list[i].neighbor_entry->netif;
3415       if ((router_netif != NULL) && (netif != NULL ? netif == router_netif :
3416           (netif_is_up(router_netif) && netif_is_link_up(router_netif)))) {
3417         /* Is the router valid, i.e., reachable or probably reachable as per
3418          * RFC 4861 Sec. 6.3.6? Note that we will never return a router that
3419          * has no neighbor cache entry, due to the netif association tests. */
3420         if (default_router_list[i].neighbor_entry->state != ND6_INCOMPLETE) {
3421           /* Is the router known to be reachable? */
3422           if ((default_router_list[i].neighbor_entry->state == ND6_REACHABLE)
3423 #if LWIP_ND6_STATIC_NBR
3424               || (default_router_list[i].neighbor_entry->state == ND6_PERMANENT)
3425 #endif
3426              ) {
3427             return i; /* valid and reachable - done! */
3428           } else if (valid_router < 0) {
3429             valid_router = i; /* valid but not known to be reachable */
3430           }
3431         }
3432       }
3433     }
3434   }
3435   if (valid_router >= 0) {
3436     return valid_router;
3437   }
3438 
3439   /* Look for any router for which we have any information at all. */
3440   /* last_router is used for round-robin selection of incomplete routers, as
3441    * recommended in RFC 4861 Sec. 6.3.6 point (2). Advance only when picking a
3442    * route, to select the same router as next-hop target in the common case. */
3443   if ((netif == NULL) && (++last_router >= LWIP_ND6_NUM_ROUTERS)) {
3444     last_router = 0;
3445   }
3446   i = last_router;
3447   for (j = 0; j < LWIP_ND6_NUM_ROUTERS; j++) {
3448     if (default_router_list[i].neighbor_entry != NULL) {
3449       router_netif = default_router_list[i].neighbor_entry->netif;
3450       if ((router_netif != NULL) && (netif != NULL ? netif == router_netif :
3451           (netif_is_up(router_netif) && netif_is_link_up(router_netif)))) {
3452         return i;
3453       }
3454     }
3455     if (++i >= LWIP_ND6_NUM_ROUTERS) {
3456       i = 0;
3457     }
3458   }
3459 
3460   /* no suitable router found. */
3461   return -1;
3462 }
3463 
3464 /**
3465  * Find a router-announced route to the given destination. This route may be
3466  * based on an on-link prefix or a default router.
3467  *
3468  * If a suitable route is found, the returned netif is guaranteed to be in a
3469  * suitable state (up, link up) to be used for packet transmission.
3470  *
3471  * @param ip6addr the destination IPv6 address
3472  * @return the netif to use for the destination, or NULL if none found
3473  */
3474 struct netif *
nd6_find_route(const ip6_addr_t * ip6addr)3475 nd6_find_route(const ip6_addr_t *ip6addr)
3476 {
3477   struct netif *netif;
3478   s8_t i;
3479 
3480   /* @todo decide if it makes sense to check the destination cache first */
3481 
3482   /* Check if there is a matching on-link prefix. There may be multiple
3483    * matches. Pick the first one that is associated with a suitable netif. */
3484   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) {
3485     netif = prefix_list[i].netif;
3486     if ((netif != NULL) && ip6_addr_netcmp(&prefix_list[i].prefix, ip6addr) &&
3487         netif_is_up(netif) && netif_is_link_up(netif)) {
3488       return netif;
3489     }
3490   }
3491 
3492   /* No on-link prefix match. Find a router that can forward the packet. */
3493   i = nd6_select_router(ip6addr, NULL);
3494   if (i >= 0) {
3495     LWIP_ASSERT("selected router must have a neighbor entry",
3496       default_router_list[i].neighbor_entry != NULL);
3497     return default_router_list[i].neighbor_entry->netif;
3498   }
3499 
3500   return NULL;
3501 }
3502 
3503 /**
3504  * Find an entry for a default router.
3505  *
3506  * @param router_addr the IPv6 address of the router
3507  * @param netif the netif on which the router is found, if known
3508  * @return the index of the router entry, or -1 if not found
3509  */
3510 static s8_t
nd6_get_router(const ip6_addr_t * router_addr,struct netif * netif)3511 nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif)
3512 {
3513   s8_t i;
3514 
3515   IP6_ADDR_ZONECHECK_NETIF(router_addr, netif);
3516 
3517   /* Look for router. */
3518   for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) {
3519     if ((default_router_list[i].neighbor_entry != NULL) &&
3520         ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) &&
3521         ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) {
3522       return i;
3523     }
3524   }
3525 
3526   /* router not found. */
3527   return -1;
3528 }
3529 
3530 /**
3531  * Create a new entry for a default router.
3532  *
3533  * @param router_addr the IPv6 address of the router
3534  * @param netif the netif on which the router is connected, if known
3535  * @return the index on the router table, or -1 if could not be created
3536  */
3537 static s8_t
nd6_new_router(const ip6_addr_t * router_addr,struct netif * netif)3538 nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif)
3539 {
3540   s8_t router_index;
3541   s8_t free_router_index;
3542   s8_t neighbor_index;
3543 
3544   IP6_ADDR_ZONECHECK_NETIF(router_addr, netif);
3545 
3546   /* Do we have a neighbor entry for this router? */
3547   neighbor_index = nd6_find_neighbor_cache_entry(router_addr, netif);
3548   if (neighbor_index < 0) {
3549     /* Create a neighbor entry for this router. */
3550     neighbor_index = nd6_new_neighbor_cache_entry();
3551     if (neighbor_index < 0) {
3552       /* Could not create neighbor entry for this router. */
3553       ND6_STATS_INC(nd6.cache_full);
3554       return -1;
3555     }
3556     ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr);
3557     neighbor_cache[neighbor_index].netif = netif;
3558     neighbor_cache[neighbor_index].q = NULL;
3559     neighbor_cache[neighbor_index].state = ND6_INCOMPLETE;
3560     neighbor_cache[neighbor_index].counter.probes_sent = 1;
3561     nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST);
3562   }
3563 
3564   /* Mark neighbor as router. */
3565   neighbor_cache[neighbor_index].isrouter = 1;
3566 
3567   /* Look for empty entry. */
3568   free_router_index = LWIP_ND6_NUM_ROUTERS;
3569   for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) {
3570     /* check if router already exists (this is a special case for 2 netifs on the same subnet
3571        - e.g. wifi and cable) */
3572     if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){
3573       return router_index;
3574     }
3575     if (default_router_list[router_index].neighbor_entry == NULL) {
3576       /* remember lowest free index to create a new entry */
3577       free_router_index = router_index;
3578     }
3579   }
3580   if (free_router_index < LWIP_ND6_NUM_ROUTERS) {
3581     default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
3582     return free_router_index;
3583   }
3584 
3585   /* Could not create a router entry. */
3586 
3587   /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */
3588   neighbor_cache[neighbor_index].isrouter = 0;
3589 
3590   /* router not found. */
3591   return -1;
3592 }
3593 
3594 /*
3595  * Will free any resources associated with a default router list
3596  * entry, and will mark it as unused.
3597  *
3598  * @param i the default entry index to free
3599  */
3600 static void
nd6_free_router(s8_t i)3601 nd6_free_router(s8_t i)
3602 {
3603   if ((i < 0) || (i >= LWIP_ND6_NUM_ROUTERS)) {
3604     return;
3605   }
3606 
3607   /*
3608    * the node MUST remove that router from the Default Router List and update
3609    * the Destination Cache entries for all destinations using that neighbor as
3610    * a router as specified in Section 7.3.3.
3611    */
3612   if (default_router_list[i].neighbor_entry != NULL) {
3613     s8_t j;
3614     for (j = 0; j < LWIP_ND6_NUM_DESTINATIONS; j++) {
3615       if (ip6_addr_cmp(&destination_cache[j].next_hop_addr,
3616           &default_router_list[i].neighbor_entry->next_hop_address)) {
3617         ip6_addr_set_any(&destination_cache[j].destination_addr);
3618       }
3619     }
3620     default_router_list[i].neighbor_entry->isrouter = 0;
3621     default_router_list[i].neighbor_entry = NULL;
3622     default_router_list[i].invalidation_timer = 0;
3623     default_router_list[i].flags = 0;
3624   }
3625   return;
3626 }
3627 
3628 /**
3629  * Find the cached entry for an on-link prefix.
3630  *
3631  * @param prefix the IPv6 prefix that is on-link
3632  * @param netif the netif on which the prefix is on-link
3633  * @return the index on the prefix table, or -1 if not found
3634  */
3635 static s8_t
nd6_get_onlink_prefix(const ip6_addr_t * prefix,struct netif * netif)3636 nd6_get_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif)
3637 {
3638   s8_t i;
3639 
3640   /* Look for prefix in list. */
3641   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) {
3642     if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) &&
3643         (prefix_list[i].netif == netif)) {
3644       return i;
3645     }
3646   }
3647 
3648   /* Entry not available. */
3649   return -1;
3650 }
3651 #if defined(LWIP_RA_PREFIX_DYNAMIC) && LWIP_RA_PREFIX_DYNAMIC
3652 static s8_t
nd6_get_onlink_prefix_with_len(const ip6_addr_t * prefix,u8_t len,struct netif * netif)3653 nd6_get_onlink_prefix_with_len(const ip6_addr_t *prefix, u8_t len, struct netif *netif)
3654 {
3655   s8_t i;
3656 
3657   /* Look for prefix in list. */
3658   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) {
3659     if ((ip6_addr_prefix_netcmp(&(prefix_list[i].prefix), prefix, len >> 3)) &&
3660         (prefix_list[i].prefix_len == len) &&
3661         (prefix_list[i].netif == netif)) {
3662       return i;
3663     }
3664   }
3665 
3666   /* Entry not available. */
3667   return -1;
3668 }
3669 #endif
3670 
3671 /**
3672  * Creates a new entry for an on-link prefix.
3673  *
3674  * @param prefix the IPv6 prefix that is on-link
3675  * @param netif the netif on which the prefix is on-link
3676  * @return the index on the prefix table, or -1 if not created
3677  */
3678 static s8_t
nd6_new_onlink_prefix(const ip6_addr_t * prefix,struct netif * netif)3679 nd6_new_onlink_prefix(const ip6_addr_t *prefix, struct netif *netif)
3680 {
3681   s8_t i;
3682 
3683   /* Create new entry. */
3684   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) {
3685     if ((prefix_list[i].netif == NULL) ||
3686         (prefix_list[i].invalidation_timer == 0)) {
3687       /* Found empty prefix entry. */
3688       prefix_list[i].netif = netif;
3689       ip6_addr_set(&(prefix_list[i].prefix), prefix);
3690       return i;
3691     }
3692   }
3693 
3694   /* Entry not available. */
3695   return -1;
3696 }
3697 
3698 /**
3699  * Determine the next hop for a destination. Will determine if the
3700  * destination is on-link, else a suitable on-link router is selected.
3701  *
3702  * The last entry index is cached for fast entry search.
3703  *
3704  * @param ip6addr the destination address
3705  * @param netif the netif on which the packet will be sent
3706  * @return the neighbor cache entry for the next hop, ERR_RTE if no
3707  *         suitable next hop was found, ERR_MEM if no cache entry
3708  *         could be created
3709  */
3710 static s8_t
nd6_get_next_hop_entry(const ip6_addr_t * ip6addr,struct netif * netif)3711 nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
3712 {
3713 #ifdef LWIP_HOOK_ND6_GET_GW
3714   const ip6_addr_t *next_hop_addr;
3715 #endif /* LWIP_HOOK_ND6_GET_GW */
3716   s8_t i;
3717   s16_t dst_idx;
3718 
3719   IP6_ADDR_ZONECHECK_NETIF(ip6addr, netif);
3720 
3721 #if LWIP_NETIF_HWADDRHINT
3722   if (netif->hints != NULL) {
3723     /* per-pcb cached entry was given */
3724     netif_addr_idx_t addr_hint = netif->hints->addr_hint;
3725     if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) {
3726       nd6_cached_destination_index = addr_hint;
3727     }
3728   }
3729 #endif /* LWIP_NETIF_HWADDRHINT */
3730 
3731   /* Look for ip6addr in destination cache. */
3732   if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) {
3733     /* the cached entry index is the right one! */
3734     /* do nothing. */
3735     ND6_STATS_INC(nd6.cachehit);
3736   } else {
3737     /* Search destination cache. */
3738     dst_idx = nd6_find_destination_cache_entry(ip6addr);
3739     if (dst_idx >= 0) {
3740       /* found destination entry. make it our new cached index. */
3741       LWIP_ASSERT("type overflow", (size_t)dst_idx < NETIF_ADDR_IDX_MAX);
3742       nd6_cached_destination_index = (netif_addr_idx_t)dst_idx;
3743     } else {
3744       /* Not found. Create a new destination entry. */
3745       dst_idx = nd6_new_destination_cache_entry();
3746       if (dst_idx >= 0) {
3747         /* got new destination entry. make it our new cached index. */
3748         LWIP_ASSERT("type overflow", (size_t)dst_idx < NETIF_ADDR_IDX_MAX);
3749         nd6_cached_destination_index = (netif_addr_idx_t)dst_idx;
3750       } else {
3751         /* Could not create a destination cache entry. */
3752         ND6_STATS_INC(nd6.cache_full);
3753         return ERR_MEM;
3754       }
3755 
3756       /* Copy dest address to destination cache. */
3757       ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr);
3758 
3759       /* Now find the next hop. is it a neighbor? */
3760       if (ip6_addr_islinklocal(ip6addr)
3761 #if !LWIP_RIPPLE
3762          || nd6_is_prefix_in_netif(ip6addr, netif)
3763 #endif
3764          ) {
3765         /* Destination in local link. */
3766         destination_cache[nd6_cached_destination_index].pmtu = netif_mtu6(netif);
3767         ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr);
3768 #ifdef LWIP_HOOK_ND6_GET_GW
3769       } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) {
3770         /* Next hop for destination provided by hook function. */
3771         destination_cache[nd6_cached_destination_index].pmtu = netif->mtu;
3772         ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr);
3773 #endif /* LWIP_HOOK_ND6_GET_GW */
3774 #if LWIP_ND6_ROUTER
3775       /* should try the same prefix addr if the node is a sta */
3776       } else if ((netif->forwarding == 0) && nd6_is_prefix_in_netif(ip6addr, netif)) {
3777         destination_cache[nd6_cached_destination_index].pmtu = netif_mtu6(netif);
3778         ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr,
3779                       destination_cache[nd6_cached_destination_index].destination_addr);
3780 #endif
3781       } else {
3782         /* We need to select a router. */
3783         i = nd6_select_router(ip6addr, netif);
3784         if (i < 0) {
3785           /* No router found. */
3786           ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr));
3787           return ERR_RTE;
3788         }
3789         destination_cache[nd6_cached_destination_index].pmtu = netif_mtu6(netif); /* Start with netif mtu, correct through ICMPv6 if necessary */
3790         ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address);
3791       }
3792     }
3793   }
3794 
3795 #if LWIP_NETIF_HWADDRHINT
3796   if (netif->hints != NULL) {
3797     /* per-pcb cached entry was given */
3798     netif->hints->addr_hint = nd6_cached_destination_index;
3799   }
3800 #endif /* LWIP_NETIF_HWADDRHINT */
3801 
3802   /* Look in neighbor cache for the next-hop address. */
3803   if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr),
3804                    &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) {
3805     /* Cache hit. */
3806     /* Do nothing. */
3807     ND6_STATS_INC(nd6.cachehit);
3808   } else {
3809     i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr), netif);
3810     if (i >= 0) {
3811       /* Found a matching record, make it new cached entry. */
3812       nd6_cached_neighbor_index = i;
3813     } else {
3814       /* Neighbor not in cache. Make a new entry. */
3815       i = nd6_new_neighbor_cache_entry();
3816       if (i >= 0) {
3817         /* got new neighbor entry. make it our new cached index. */
3818         nd6_cached_neighbor_index = i;
3819       } else {
3820         /* Could not create a neighbor cache entry. */
3821         ND6_STATS_INC(nd6.cache_full);
3822         return ERR_MEM;
3823       }
3824 
3825       /* Initialize fields. */
3826       ip6_addr_copy(neighbor_cache[i].next_hop_address,
3827                    destination_cache[nd6_cached_destination_index].next_hop_addr);
3828       neighbor_cache[i].isrouter = 0;
3829       neighbor_cache[i].netif = netif;
3830       neighbor_cache[i].state = ND6_INCOMPLETE;
3831       neighbor_cache[i].counter.probes_sent = 1;
3832       nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST);
3833     }
3834   }
3835 
3836   /* Reset this destination's age. */
3837   destination_cache[nd6_cached_destination_index].age = 0;
3838 
3839   return nd6_cached_neighbor_index;
3840 }
3841 
netif_find_dst_ip6addr_mac_addr(const ip_addr_t * ipaddr,ip_addr_t ** dst_addr,struct eth_addr ** eth_ret)3842 s8_t netif_find_dst_ip6addr_mac_addr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr, struct eth_addr **eth_ret)
3843 {
3844   struct netif *netif = NULL;
3845 
3846   int dst_index;
3847   int neighbour_index;
3848 
3849   netif = netif_find_by_ipaddr(ipaddr);
3850   if (netif == NULL) {
3851     return -1;
3852   }
3853 
3854   dst_index = nd6_find_destination_cache_entry(&((*dst_addr)->u_addr.ip6));
3855   if (dst_index < 0) {
3856     return -1;
3857   }
3858   neighbour_index = nd6_find_neighbor_cache_entry(&(destination_cache[dst_index].next_hop_addr), netif);
3859   if (neighbour_index < 0) {
3860     return -1;
3861   }
3862 
3863   if (memcpy_s((*eth_ret)->addr, sizeof(struct eth_addr), neighbor_cache[neighbour_index].lladdr,
3864                neighbor_cache[neighbour_index].lladdrlen) != EOK) {
3865     return -1;
3866   }
3867 
3868   return 0;
3869 }
3870 
3871 /**
3872  * Queue a packet for a neighbor.
3873  *
3874  * @param neighbor_index the index in the neighbor cache table
3875  * @param q packet to be queued
3876  * @return ERR_OK if succeeded, ERR_MEM if out of memory
3877  */
3878 static err_t
nd6_queue_packet(s8_t neighbor_index,struct pbuf * q)3879 nd6_queue_packet(s8_t neighbor_index, struct pbuf *q)
3880 {
3881   err_t result = ERR_MEM;
3882   struct pbuf *p;
3883   int copy_needed = 0;
3884 #if LWIP_ND6_QUEUEING
3885   struct nd6_q_entry *new_entry, *r;
3886 #endif /* LWIP_ND6_QUEUEING */
3887 
3888   if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) {
3889     return ERR_ARG;
3890   }
3891 
3892   /* IF q includes a pbuf that must be copied, we have to copy the whole chain
3893    * into a new PBUF_RAM. See the definition of PBUF_NEEDS_COPY for details. */
3894   p = q;
3895   while (p) {
3896     if (PBUF_NEEDS_COPY(p)) {
3897       copy_needed = 1;
3898       break;
3899     }
3900     p = p->next;
3901   }
3902   if (copy_needed) {
3903     /* copy the whole packet into new pbufs */
3904     p = pbuf_clone(PBUF_LINK, PBUF_RAM, q);
3905     while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) {
3906       /* Free oldest packet (as per RFC recommendation) */
3907 #if LWIP_ND6_QUEUEING
3908       r = neighbor_cache[neighbor_index].q;
3909       neighbor_cache[neighbor_index].q = r->next;
3910       r->next = NULL;
3911       nd6_free_q(r);
3912 #else /* LWIP_ND6_QUEUEING */
3913       pbuf_free(neighbor_cache[neighbor_index].q);
3914       neighbor_cache[neighbor_index].q = NULL;
3915 #endif /* LWIP_ND6_QUEUEING */
3916       p = pbuf_clone(PBUF_LINK, PBUF_RAM, q);
3917     }
3918     if (p != NULL) {
3919       p->flags = q->flags;
3920 #if LWIP_SO_PRIORITY
3921       p->priority = q->priority;
3922 #endif /* LWIP_SO_PRIORITY */
3923     }
3924   } else {
3925     /* referencing the old pbuf is enough */
3926     p = q;
3927     pbuf_ref(p);
3928   }
3929   /* packet was copied/ref'd? */
3930   if (p != NULL) {
3931     /* queue packet ... */
3932 #if LWIP_ND6_QUEUEING
3933     /* allocate a new nd6 queue entry */
3934     new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE);
3935     if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) {
3936       /* Free oldest packet (as per RFC recommendation) */
3937       r = neighbor_cache[neighbor_index].q;
3938       neighbor_cache[neighbor_index].q = r->next;
3939       r->next = NULL;
3940       nd6_free_q(r);
3941       new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE);
3942     }
3943     if (new_entry != NULL) {
3944       new_entry->next = NULL;
3945       new_entry->p = p;
3946       if (neighbor_cache[neighbor_index].q != NULL) {
3947         /* queue was already existent, append the new entry to the end */
3948         r = neighbor_cache[neighbor_index].q;
3949         while (r->next != NULL) {
3950           r = r->next;
3951         }
3952         r->next = new_entry;
3953       } else {
3954         /* queue did not exist, first item in queue */
3955         neighbor_cache[neighbor_index].q = new_entry;
3956       }
3957       LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index));
3958       result = ERR_OK;
3959     } else {
3960       /* the pool MEMP_ND6_QUEUE is empty */
3961       pbuf_free(p);
3962       LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p));
3963       /* { result == ERR_MEM } through initialization */
3964     }
3965 #else /* LWIP_ND6_QUEUEING */
3966     /* Queue a single packet. If an older packet is already queued, free it as per RFC. */
3967     if (neighbor_cache[neighbor_index].q != NULL) {
3968       pbuf_free(neighbor_cache[neighbor_index].q);
3969     }
3970     neighbor_cache[neighbor_index].q = p;
3971     LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index));
3972     result = ERR_OK;
3973 #endif /* LWIP_ND6_QUEUEING */
3974   } else {
3975     LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q));
3976     /* { result == ERR_MEM } through initialization */
3977   }
3978 
3979   return result;
3980 }
3981 
3982 #if LWIP_ND6_QUEUEING
3983 /**
3984  * Free a complete queue of nd6 q entries
3985  *
3986  * @param q a queue of nd6_q_entry to free
3987  */
3988 static void
nd6_free_q(struct nd6_q_entry * q)3989 nd6_free_q(struct nd6_q_entry *q)
3990 {
3991   struct nd6_q_entry *r;
3992   LWIP_ASSERT("q != NULL", q != NULL);
3993   LWIP_ASSERT("q->p != NULL", q->p != NULL);
3994   while (q) {
3995     r = q;
3996     q = q->next;
3997     LWIP_ASSERT("r->p != NULL", (r->p != NULL));
3998     pbuf_free(r->p);
3999     memp_free(MEMP_ND6_QUEUE, r);
4000   }
4001 }
4002 #endif /* LWIP_ND6_QUEUEING */
4003 
4004 /**
4005  * Send queued packets for a neighbor
4006  *
4007  * @param i the neighbor to send packets to
4008  */
4009 static void
nd6_send_q(s8_t i)4010 nd6_send_q(s8_t i)
4011 {
4012   struct ip6_hdr *ip6hdr;
4013   ip6_addr_t dest;
4014 #if LWIP_ND6_QUEUEING
4015   struct nd6_q_entry *q;
4016 #endif /* LWIP_ND6_QUEUEING */
4017 
4018   if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) {
4019     return;
4020   }
4021 
4022 #if LWIP_ND6_QUEUEING
4023   while (neighbor_cache[i].q != NULL) {
4024     /* remember first in queue */
4025     q = neighbor_cache[i].q;
4026     /* pop first item off the queue */
4027     neighbor_cache[i].q = q->next;
4028     /* Get ipv6 header. */
4029     ip6hdr = (struct ip6_hdr *)(q->p->payload);
4030     /* Create an aligned copy. */
4031     ip6_addr_copy_from_packed(dest, ip6hdr->dest);
4032     /* Restore the zone, if applicable. */
4033     ip6_addr_assign_zone(&dest, IP6_UNKNOWN, neighbor_cache[i].netif);
4034     LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n",
4035                 (void *)q->p, (s16_t)i));
4036     /* send the queued IPv6 packet */
4037     (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest);
4038     /* free the queued IP packet */
4039     pbuf_free(q->p);
4040     /* now queue entry can be freed */
4041     memp_free(MEMP_ND6_QUEUE, q);
4042   }
4043 #else /* LWIP_ND6_QUEUEING */
4044   if (neighbor_cache[i].q != NULL) {
4045     /* Get ipv6 header. */
4046     ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload);
4047     /* Create an aligned copy. */
4048     ip6_addr_copy_from_packed(dest, ip6hdr->dest);
4049     /* Restore the zone, if applicable. */
4050     ip6_addr_assign_zone(&dest, IP6_UNKNOWN, neighbor_cache[i].netif);
4051     /* send the queued IPv6 packet */
4052     (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest);
4053     /* free the queued IP packet */
4054     pbuf_free(neighbor_cache[i].q);
4055     neighbor_cache[i].q = NULL;
4056   }
4057 #endif /* LWIP_ND6_QUEUEING */
4058 }
4059 
4060 /**
4061  * A packet is to be transmitted to a specific IPv6 destination on a specific
4062  * interface. Check if we can find the hardware address of the next hop to use
4063  * for the packet. If so, give the hardware address to the caller, which should
4064  * use it to send the packet right away. Otherwise, enqueue the packet for
4065  * later transmission while looking up the hardware address, if possible.
4066  *
4067  * As such, this function returns one of three different possible results:
4068  *
4069  * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now.
4070  * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later.
4071  * - not ERR_OK: something went wrong; forward the error upward in the stack.
4072  *
4073  * @param netif The lwIP network interface on which the IP packet will be sent.
4074  * @param q The pbuf(s) containing the IP packet to be sent.
4075  * @param ip6addr The destination IPv6 address of the packet.
4076  * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning
4077  *        the packet has been queued).
4078  * @return
4079  * - ERR_OK on success, ERR_RTE if no route was found for the packet,
4080  * or ERR_MEM if low memory conditions prohibit sending the packet at all.
4081  */
4082 err_t
nd6_get_next_hop_addr_or_queue(struct netif * netif,struct pbuf * q,const ip6_addr_t * ip6addr,const u8_t ** hwaddrp)4083 nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp)
4084 {
4085   s8_t i;
4086 
4087   /* Get next hop record. */
4088   i = nd6_get_next_hop_entry(ip6addr, netif);
4089   if (i < 0) {
4090     /* failed to get a next hop neighbor record. */
4091     return i;
4092   }
4093 
4094   /* Now that we have a destination record, send or queue the packet. */
4095   if (neighbor_cache[i].state == ND6_STALE) {
4096     /* Switch to delay state. */
4097     neighbor_cache[i].state = ND6_DELAY;
4098     neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL;
4099   }
4100   /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */
4101   if ((neighbor_cache[i].state == ND6_REACHABLE) ||
4102       (neighbor_cache[i].state == ND6_DELAY) ||
4103       (neighbor_cache[i].state == ND6_PROBE)
4104 #if LWIP_ND6_STATIC_NBR
4105       || (neighbor_cache[i].state == ND6_PERMANENT)
4106 #endif
4107      ) {
4108     /* Tell the caller to send out the packet now. */
4109     *hwaddrp = neighbor_cache[i].lladdr;
4110     return ERR_OK;
4111   }
4112 
4113   /* We should queue packet on this interface. */
4114   *hwaddrp = NULL;
4115   return nd6_queue_packet(i, q);
4116 }
4117 
4118 
4119 /**
4120  * Get the Path MTU for a destination.
4121  *
4122  * @param ip6addr the destination address
4123  * @param netif the netif on which the packet will be sent
4124  * @return the Path MTU, if known, or the netif default MTU
4125  */
4126 u16_t
nd6_get_destination_mtu(const ip6_addr_t * ip6addr,struct netif * netif)4127 nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif)
4128 {
4129   s16_t i;
4130 
4131   i = nd6_find_destination_cache_entry(ip6addr);
4132   if (i >= 0) {
4133     if (destination_cache[i].pmtu > 0) {
4134       return destination_cache[i].pmtu;
4135     }
4136   }
4137 
4138   if (netif != NULL) {
4139     return netif_mtu6(netif);
4140   }
4141 
4142   return IP6_MIN_MTU_LENGTH; /* Minimum MTU */
4143 }
4144 
4145 
4146 #if LWIP_ND6_TCP_REACHABILITY_HINTS
4147 /**
4148  * Provide the Neighbor discovery process with a hint that a
4149  * destination is reachable. Called by tcp_receive when ACKs are
4150  * received or sent (as per RFC). This is useful to avoid sending
4151  * NS messages every 30 seconds.
4152  *
4153  * @param ip6addr the destination address which is know to be reachable
4154  *                by an upper layer protocol (TCP)
4155  */
4156 void
nd6_reachability_hint(const ip6_addr_t * ip6addr)4157 nd6_reachability_hint(const ip6_addr_t *ip6addr)
4158 {
4159   s8_t i;
4160   s16_t dst_idx;
4161   struct netif *netif = NULL;
4162 
4163   /* Find destination in cache. */
4164   if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) {
4165     dst_idx = nd6_cached_destination_index;
4166     ND6_STATS_INC(nd6.cachehit);
4167   } else {
4168     dst_idx = nd6_find_destination_cache_entry(ip6addr);
4169   }
4170   if (dst_idx < 0) {
4171     return;
4172   }
4173 
4174   /* Find next hop neighbor in cache. */
4175   if (ip6_addr_cmp(&(destination_cache[dst_idx].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) {
4176     i = nd6_cached_neighbor_index;
4177     ND6_STATS_INC(nd6.cachehit);
4178   } else {
4179     netif = netif_find_by_ipaddr(ip_current_dest_addr());
4180     i = nd6_find_neighbor_cache_entry(&(destination_cache[dst_idx].next_hop_addr), netif);
4181   }
4182   if (i < 0) {
4183     ND6_STATS_INC(nd6.cache_miss);
4184     return;
4185   }
4186 
4187   /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */
4188   if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) {
4189     return;
4190   }
4191 
4192   /* Set reachability state. */
4193   neighbor_cache[i].state = ND6_REACHABLE;
4194   neighbor_cache[i].counter.reachable_time = reachable_time;
4195 }
4196 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
4197 
4198 /**
4199  * Remove all prefix, neighbor_cache and router entries of the specified netif.
4200  *
4201  * @param netif points to a network interface
4202  */
4203 void
nd6_cleanup_netif(struct netif * netif)4204 nd6_cleanup_netif(struct netif *netif)
4205 {
4206   u8_t i, j;
4207   s8_t router_index;
4208   for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) {
4209     if (prefix_list[i].netif == netif) {
4210       prefix_list[i].netif = NULL;
4211     }
4212   }
4213   for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) {
4214     if (neighbor_cache[i].netif == netif) {
4215       for (j = 0; j < LWIP_ND6_NUM_DESTINATIONS; j++) {
4216         if (!ip6_addr_isany(&destination_cache[j].destination_addr) &&
4217             ip6_addr_cmp(&(destination_cache[j].next_hop_addr), &(neighbor_cache[i].next_hop_address))) {
4218           ip6_addr_set_any(&destination_cache[j].destination_addr);
4219         }
4220       }
4221 
4222       for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) {
4223         if (default_router_list[router_index].neighbor_entry == &neighbor_cache[i]) {
4224           default_router_list[router_index].neighbor_entry->isrouter = 0;
4225           default_router_list[router_index].neighbor_entry = NULL;
4226           default_router_list[router_index].invalidation_timer = 0;
4227           default_router_list[router_index].flags = 0;
4228         }
4229       }
4230       neighbor_cache[i].isrouter = 0;
4231       nd6_free_neighbor_cache_entry((s8_t)i);
4232     }
4233   }
4234 #if (LWIP_RIPPLE && LWIP_CONF_UPDATE_BEACON_PRIORITY)
4235   beacon_priority_update(0);
4236 #endif
4237 }
4238 
4239 #if LWIP_IPV6_MLD
4240 /**
4241  * The state of a local IPv6 address entry is about to change. If needed, join
4242  * or leave the solicited-node multicast group for the address.
4243  *
4244  * @param netif The netif that owns the address.
4245  * @param addr_idx The index of the address.
4246  * @param new_state The new (IP6_ADDR_) state for the address.
4247  */
4248 void
nd6_adjust_mld_membership(struct netif * netif,s8_t addr_idx,u8_t new_state)4249 nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state)
4250 {
4251   u8_t old_state, old_member, new_member;
4252 
4253   old_state = netif_ip6_addr_state(netif, addr_idx);
4254 
4255   /* Determine whether we were, and should be, a member of the solicited-node
4256    * multicast group for this address. For tentative addresses, the group is
4257    * not joined until the address enters the TENTATIVE_1 (or VALID) state. */
4258   old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_DUPLICATED && old_state != IP6_ADDR_TENTATIVE);
4259   new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_DUPLICATED && new_state != IP6_ADDR_TENTATIVE);
4260 
4261   if (old_member != new_member) {
4262     ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]);
4263     ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST, netif);
4264 
4265     if (new_member) {
4266       mld6_joingroup_netif(netif, &multicast_address);
4267     } else {
4268       mld6_leavegroup_netif(netif, &multicast_address);
4269     }
4270   }
4271 }
4272 #endif /* LWIP_IPV6_MLD */
4273 
4274 #if LWIP_IPV6_AUTOCONFIG
4275 /*
4276  * clear the netif's IPV6 address which is autoconfiged from RA
4277  *
4278  * @param netif the netif to clear IPV6 address
4279  */
4280 void
nd6_clear_netif_autoconf_address(struct netif * netif)4281 nd6_clear_netif_autoconf_address(struct netif *netif)
4282 {
4283   s8_t i, j;
4284 
4285   if (netif == NULL) {
4286     return;
4287   }
4288 
4289   /* Skip 0 index (link-local address) */
4290   for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) {
4291     if (netif_ip6_addr_state(netif, j) != IP6_ADDR_INVALID) {
4292       i = nd6_get_onlink_prefix((ip6_addr_t *)netif_ip6_addr(netif, j), netif);
4293       if ((i >= 0) && !netif_ip6_addr_isstatic(netif, j) && !netif_ip6_addr_isdhcp6(netif, j)) {
4294         netif_ip6_addr_set_state(netif, j, IP6_ADDR_INVALID);
4295       }
4296     }
4297   }
4298 
4299   return;
4300 }
4301 #endif
4302 
4303 /** Netif was added, set up, or reconnected (link up) */
4304 void
nd6_restart_netif(struct netif * netif)4305 nd6_restart_netif(struct netif *netif)
4306 {
4307 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
4308   /* Send Router Solicitation messages (see RFC 4861, ch. 6.3.7). */
4309   netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
4310 #else
4311   LWIP_UNUSED_ARG(netif);
4312 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
4313 }
4314 
4315 /*
4316  * Report ND6 messages for this interface
4317  *
4318  * @param netif network interface on which report ND6 messages
4319  */
4320 void
nd6_report_groups(struct netif * netif,s8_t addr_idx)4321 nd6_report_groups(struct netif *netif, s8_t addr_idx)
4322 {
4323   int i;
4324   if ((netif->flags & (NETIF_FLAG_ETHARP)) == 0) {
4325     return;
4326   }
4327   /*
4328    * Publish all new address after hw addr changed, note : link local address remains same,
4329    * since it needs to be reconfigured by user.
4330    */
4331   /*
4332    * RFC4861 section 7.2.6: The Override flag MAY be set to either zero or one. In either case, neighboring
4333    * nodes will immediately change the state of their Neighbor Cache entries for the Target Address to STALE,
4334    * prompting them to verify the path for reachability. If the Override flag is set to one, neighboring nodes will
4335    * install the new link-layer address in their caches. Otherwise, they will ignore the new link-layer address,
4336    * choosing instead to probe the cached address.
4337    */
4338   /*
4339    * lwip sets Override flag to one to make the neighboring nodes update their neighbor cache immediately,
4340    * this would avoid network failure if the peer side still use the old hw address.
4341    */
4342   if (addr_idx == (s8_t)LWIP_INVALID_IPV6_IDX) {
4343     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
4344       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
4345         nd6_send_na(netif, netif_ip6_addr(netif, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST);
4346       }
4347     }
4348 #if (LWIP_NAT64 && LWIP_NA_PROXY_UNSOLICITED)
4349     nat64_proxy_unsolicited_na(netif);
4350 #endif
4351   } else {
4352     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) {
4353       nd6_send_na(netif, netif_ip6_addr(netif, addr_idx), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST);
4354     }
4355   }
4356 }
4357 
4358 #endif /* LWIP_IPV6 */
4359