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