1 /** @file
2 * @brief IPv6 Neighbor related functions
3 */
4
5 /*
6 * Copyright (c) 2018 Intel Corporation
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 /* By default this prints too much data, set the value to 1 to see
12 * neighbor cache contents.
13 */
14 #define NET_DEBUG_NBR 0
15
16 #include <logging/log.h>
17 LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL);
18
19 #include <errno.h>
20 #include <stdlib.h>
21 #include <net/net_core.h>
22 #include <net/net_pkt.h>
23 #include <net/net_stats.h>
24 #include <net/net_context.h>
25 #include <net/net_mgmt.h>
26 #include "net_private.h"
27 #include "connection.h"
28 #include "icmpv6.h"
29 #include "udp_internal.h"
30 #include "tcp_internal.h"
31 #include "ipv6.h"
32 #include "nbr.h"
33 #include "6lo.h"
34 #include "route.h"
35 #include "net_stats.h"
36
37 /* Timeout value to be used when allocating net buffer during various
38 * neighbor discovery procedures.
39 */
40 #define ND_NET_BUF_TIMEOUT K_MSEC(100)
41
42 /* Timeout for various buffer allocations in this file. */
43 #define NET_BUF_TIMEOUT K_MSEC(50)
44
45 /* Maximum reachable time value specified in RFC 4861 section
46 * 6.2.1. Router Configuration Variables, AdvReachableTime
47 */
48 #define MAX_REACHABLE_TIME 3600000
49
50 /* IPv6 minimum link MTU specified in RFC 8200 section 5
51 * Packet Size Issues
52 */
53 #define MIN_IPV6_MTU NET_IPV6_MTU
54 #define MAX_IPV6_MTU 0xffff
55
56 #if defined(CONFIG_NET_IPV6_NBR_CACHE) || defined(CONFIG_NET_IPV6_ND)
57 /* Global stale counter, whenever ipv6 neighbor enters into
58 * stale state, stale counter is incremented by one.
59 * When network stack tries to add new neighbor and if table
60 * is full, oldest (oldest stale counter) neighbor in stale
61 * state will be removed from the table and new entry will be
62 * added.
63 */
64 static uint32_t stale_counter;
65
66 static struct k_sem nbr_lock;
67 #endif
68
69 #if defined(CONFIG_NET_IPV6_ND)
70 static struct k_work_delayable ipv6_nd_reachable_timer;
71 static void ipv6_nd_reachable_timeout(struct k_work *work);
72 static void ipv6_nd_restart_reachable_timer(struct net_nbr *nbr, int64_t time);
73 #endif
74
75 #if defined(CONFIG_NET_IPV6_NBR_CACHE)
76
77 /* Protocol constants from RFC 4861 Chapter 10 */
78 #define MAX_MULTICAST_SOLICIT 3
79 #define MAX_UNICAST_SOLICIT 3
80 #define DELAY_FIRST_PROBE_TIME (5 * MSEC_PER_SEC)
81 #define RETRANS_TIMER 1000 /* ms */
82
83 extern void net_neighbor_data_remove(struct net_nbr *nbr);
84 extern void net_neighbor_table_clear(struct net_nbr_table *table);
85
86 /** Neighbor Solicitation reply timer */
87 static struct k_work_delayable ipv6_ns_reply_timer;
88
89 NET_NBR_POOL_INIT(net_neighbor_pool,
90 CONFIG_NET_IPV6_MAX_NEIGHBORS,
91 sizeof(struct net_ipv6_nbr_data),
92 net_neighbor_data_remove,
93 0);
94
95 NET_NBR_TABLE_INIT(NET_NBR_GLOBAL,
96 neighbor,
97 net_neighbor_pool,
98 net_neighbor_table_clear);
99
net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state)100 const char *net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state)
101 {
102 switch (state) {
103 case NET_IPV6_NBR_STATE_INCOMPLETE:
104 return "incomplete";
105 case NET_IPV6_NBR_STATE_REACHABLE:
106 return "reachable";
107 case NET_IPV6_NBR_STATE_STALE:
108 return "stale";
109 case NET_IPV6_NBR_STATE_DELAY:
110 return "delay";
111 case NET_IPV6_NBR_STATE_PROBE:
112 return "probe";
113 case NET_IPV6_NBR_STATE_STATIC:
114 return "static";
115 }
116
117 return "<invalid state>";
118 }
119
get_nbr(int idx)120 static inline struct net_nbr *get_nbr(int idx)
121 {
122 return &net_neighbor_pool[idx].nbr;
123 }
124
get_nbr_from_data(struct net_ipv6_nbr_data * data)125 static inline struct net_nbr *get_nbr_from_data(struct net_ipv6_nbr_data *data)
126 {
127 int i;
128
129 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
130 struct net_nbr *nbr = get_nbr(i);
131
132 if (nbr->data == (uint8_t *)data) {
133 return nbr;
134 }
135 }
136
137 return NULL;
138 }
139
ipv6_nbr_set_state(struct net_nbr * nbr,enum net_ipv6_nbr_state new_state)140 static void ipv6_nbr_set_state(struct net_nbr *nbr,
141 enum net_ipv6_nbr_state new_state)
142 {
143 if (new_state == net_ipv6_nbr_data(nbr)->state ||
144 net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_STATIC) {
145 return;
146 }
147
148 NET_DBG("nbr %p %s -> %s", nbr,
149 net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state),
150 net_ipv6_nbr_state2str(new_state));
151
152 net_ipv6_nbr_data(nbr)->state = new_state;
153
154 if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_STALE) {
155 if (stale_counter + 1 != UINT32_MAX) {
156 net_ipv6_nbr_data(nbr)->stale_counter = stale_counter++;
157 } else {
158 /* Global stale counter reached UINT32_MAX, reset it and
159 * respective neighbors stale counter too.
160 */
161 struct net_nbr *n = NULL;
162 struct net_ipv6_nbr_data *data = NULL;
163 int i;
164
165 k_sem_take(&nbr_lock, K_FOREVER);
166
167 stale_counter = 0U;
168
169 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
170 n = get_nbr(i);
171 if (!n || !n->ref) {
172 continue;
173 }
174
175 data = net_ipv6_nbr_data(nbr);
176 if (!data) {
177 continue;
178 }
179
180 if (data->state != NET_IPV6_NBR_STATE_STALE) {
181 continue;
182 }
183
184 data->stale_counter = stale_counter++;
185 }
186
187 k_sem_give(&nbr_lock);
188 }
189 }
190 }
191
192 struct iface_cb_data {
193 net_nbr_cb_t cb;
194 void *user_data;
195 };
196
iface_cb(struct net_if * iface,void * user_data)197 static void iface_cb(struct net_if *iface, void *user_data)
198 {
199 struct iface_cb_data *data = user_data;
200 int i;
201
202 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
203 struct net_nbr *nbr = get_nbr(i);
204
205 if (!nbr->ref || nbr->iface != iface) {
206 continue;
207 }
208
209 data->cb(nbr, data->user_data);
210 }
211 }
212
net_ipv6_nbr_foreach(net_nbr_cb_t cb,void * user_data)213 void net_ipv6_nbr_foreach(net_nbr_cb_t cb, void *user_data)
214 {
215 struct iface_cb_data cb_data = {
216 .cb = cb,
217 .user_data = user_data,
218 };
219
220 /* Return the neighbors according to network interface. This makes it
221 * easier in the callback to use the neighbor information.
222 */
223 net_if_foreach(iface_cb, &cb_data);
224 }
225
226 #if NET_DEBUG_NBR
nbr_print(void)227 void nbr_print(void)
228 {
229 int i;
230
231 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
232 struct net_nbr *nbr = get_nbr(i);
233
234 if (!nbr->ref) {
235 continue;
236 }
237
238 NET_DBG("[%d] %p %d/%d/%d/%d/%d pending %p iface %p/%d "
239 "ll %s addr %s",
240 i, nbr, nbr->ref, net_ipv6_nbr_data(nbr)->ns_count,
241 net_ipv6_nbr_data(nbr)->is_router,
242 net_ipv6_nbr_data(nbr)->state,
243 net_ipv6_nbr_data(nbr)->link_metric,
244 net_ipv6_nbr_data(nbr)->pending,
245 nbr->iface, nbr->idx,
246 nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" :
247 log_strdup(net_sprint_ll_addr(
248 net_nbr_get_lladdr(nbr->idx)->addr,
249 net_nbr_get_lladdr(nbr->idx)->len)),
250 log_strdup(net_sprint_ipv6_addr(
251 &net_ipv6_nbr_data(nbr)->addr)));
252 }
253 }
254 #else
255 #define nbr_print(...)
256 #endif
257
nbr_lookup(struct net_nbr_table * table,struct net_if * iface,const struct in6_addr * addr)258 static struct net_nbr *nbr_lookup(struct net_nbr_table *table,
259 struct net_if *iface,
260 const struct in6_addr *addr)
261 {
262 int i;
263
264 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
265 struct net_nbr *nbr = get_nbr(i);
266
267 if (!nbr->ref) {
268 continue;
269 }
270
271 if (iface && nbr->iface != iface) {
272 continue;
273 }
274
275 if (net_ipv6_addr_cmp(&net_ipv6_nbr_data(nbr)->addr, addr)) {
276 return nbr;
277 }
278 }
279
280 return NULL;
281 }
282
nbr_clear_ns_pending(struct net_ipv6_nbr_data * data)283 static inline void nbr_clear_ns_pending(struct net_ipv6_nbr_data *data)
284 {
285 data->send_ns = 0;
286
287 if (data->pending) {
288 net_pkt_unref(data->pending);
289 data->pending = NULL;
290 }
291 }
292
nbr_free(struct net_nbr * nbr)293 static inline void nbr_free(struct net_nbr *nbr)
294 {
295 NET_DBG("nbr %p", nbr);
296
297 nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
298
299 net_ipv6_nbr_data(nbr)->reachable = 0;
300 net_ipv6_nbr_data(nbr)->reachable_timeout = 0;
301
302 net_nbr_unref(nbr);
303 net_nbr_unlink(nbr, NULL);
304 }
305
net_ipv6_nbr_rm(struct net_if * iface,struct in6_addr * addr)306 bool net_ipv6_nbr_rm(struct net_if *iface, struct in6_addr *addr)
307 {
308 struct net_nbr *nbr;
309 #if defined(CONFIG_NET_MGMT_EVENT_INFO)
310 struct net_event_ipv6_nbr info;
311 #endif
312
313 nbr = nbr_lookup(&net_neighbor.table, iface, addr);
314 if (!nbr) {
315 return false;
316 }
317
318 /* Remove any routes with nbr as nexthop in first place */
319 net_route_del_by_nexthop(iface, addr);
320
321 nbr_free(nbr);
322
323 #if defined(CONFIG_NET_MGMT_EVENT_INFO)
324 info.idx = -1;
325 net_ipaddr_copy(&info.addr, addr);
326 net_mgmt_event_notify_with_info(NET_EVENT_IPV6_NBR_DEL,
327 iface, (void *) &info,
328 sizeof(struct net_event_ipv6_nbr));
329 #else
330 net_mgmt_event_notify(NET_EVENT_IPV6_NBR_DEL, iface);
331 #endif
332
333 return true;
334 }
335
336 #define NS_REPLY_TIMEOUT (1 * MSEC_PER_SEC)
337
ipv6_ns_reply_timeout(struct k_work * work)338 static void ipv6_ns_reply_timeout(struct k_work *work)
339 {
340 int64_t current = k_uptime_get();
341 struct net_nbr *nbr = NULL;
342 struct net_ipv6_nbr_data *data;
343 int i;
344
345 ARG_UNUSED(work);
346
347 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
348 int64_t remaining;
349 nbr = get_nbr(i);
350
351 if (!nbr || !nbr->ref) {
352 continue;
353 }
354
355 data = net_ipv6_nbr_data(nbr);
356 if (!data) {
357 continue;
358 }
359
360 if (!data->send_ns) {
361 continue;
362 }
363
364 remaining = data->send_ns + NS_REPLY_TIMEOUT - current;
365
366 if (remaining > 0) {
367 if (!k_work_delayable_remaining_get(
368 &ipv6_ns_reply_timer)) {
369 k_work_reschedule(&ipv6_ns_reply_timer,
370 K_MSEC(remaining));
371 }
372
373 continue;
374 }
375
376 data->send_ns = 0;
377
378 /* We did not receive reply to a sent NS */
379 if (!data->pending) {
380 /* Silently return, this is not an error as the work
381 * cannot be cancelled in certain cases.
382 */
383 continue;
384 }
385
386 NET_DBG("NS nbr %p pending %p timeout to %s", nbr,
387 data->pending,
388 log_strdup(net_sprint_ipv6_addr(
389 &NET_IPV6_HDR(data->pending)->dst)));
390
391 /* To unref when pending variable was set */
392 net_pkt_unref(data->pending);
393
394 /* To unref the original pkt allocation */
395 net_pkt_unref(data->pending);
396
397 data->pending = NULL;
398
399 net_nbr_unref(nbr);
400 }
401 }
402
nbr_init(struct net_nbr * nbr,struct net_if * iface,const struct in6_addr * addr,bool is_router,enum net_ipv6_nbr_state state)403 static void nbr_init(struct net_nbr *nbr, struct net_if *iface,
404 const struct in6_addr *addr, bool is_router,
405 enum net_ipv6_nbr_state state)
406 {
407 nbr->idx = NET_NBR_LLADDR_UNKNOWN;
408 nbr->iface = iface;
409
410 net_ipaddr_copy(&net_ipv6_nbr_data(nbr)->addr, addr);
411 ipv6_nbr_set_state(nbr, state);
412 net_ipv6_nbr_data(nbr)->is_router = is_router;
413 net_ipv6_nbr_data(nbr)->pending = NULL;
414 net_ipv6_nbr_data(nbr)->send_ns = 0;
415
416 #if defined(CONFIG_NET_IPV6_ND)
417 net_ipv6_nbr_data(nbr)->reachable = 0;
418 net_ipv6_nbr_data(nbr)->reachable_timeout = 0;
419 #endif
420 }
421
nbr_new(struct net_if * iface,const struct in6_addr * addr,bool is_router,enum net_ipv6_nbr_state state)422 static struct net_nbr *nbr_new(struct net_if *iface,
423 const struct in6_addr *addr, bool is_router,
424 enum net_ipv6_nbr_state state)
425 {
426 struct net_nbr *nbr = net_nbr_get(&net_neighbor.table);
427
428 if (!nbr) {
429 return NULL;
430 }
431
432 nbr_init(nbr, iface, addr, is_router, state);
433
434 NET_DBG("nbr %p iface %p/%d state %d IPv6 %s",
435 nbr, iface, net_if_get_by_iface(iface), state,
436 log_strdup(net_sprint_ipv6_addr(addr)));
437
438 return nbr;
439 }
440
dbg_update_neighbor_lladdr(const struct net_linkaddr * new_lladdr,const struct net_linkaddr_storage * old_lladdr,const struct in6_addr * addr)441 static void dbg_update_neighbor_lladdr(const struct net_linkaddr *new_lladdr,
442 const struct net_linkaddr_storage *old_lladdr,
443 const struct in6_addr *addr)
444 {
445 char out[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
446
447 snprintk(out, sizeof(out), "%s",
448 net_sprint_ll_addr(old_lladdr->addr, old_lladdr->len));
449
450 NET_DBG("Updating neighbor %s lladdr %s (was %s)",
451 log_strdup(net_sprint_ipv6_addr(addr)),
452 log_strdup(net_sprint_ll_addr(new_lladdr->addr,
453 new_lladdr->len)),
454 log_strdup(out));
455 }
456
dbg_update_neighbor_lladdr_raw(uint8_t * new_lladdr,struct net_linkaddr_storage * old_lladdr,struct in6_addr * addr)457 static void dbg_update_neighbor_lladdr_raw(uint8_t *new_lladdr,
458 struct net_linkaddr_storage *old_lladdr,
459 struct in6_addr *addr)
460 {
461 struct net_linkaddr lladdr = {
462 .len = old_lladdr->len,
463 .addr = new_lladdr,
464 };
465
466 dbg_update_neighbor_lladdr(&lladdr, old_lladdr, addr);
467 }
468
469 #define dbg_addr(action, pkt_str, src, dst, pkt) \
470 do { \
471 NET_DBG("%s %s from %s to %s iface %p/%d", \
472 action, pkt_str, \
473 log_strdup(net_sprint_ipv6_addr(src)), \
474 log_strdup(net_sprint_ipv6_addr(dst)), \
475 net_pkt_iface(pkt), \
476 net_if_get_by_iface(net_pkt_iface(pkt))); \
477 } while (0)
478
479 #define dbg_addr_recv(pkt_str, src, dst, pkt) \
480 dbg_addr("Received", pkt_str, src, dst, pkt)
481
482 #define dbg_addr_sent(pkt_str, src, dst, pkt) \
483 dbg_addr("Sent", pkt_str, src, dst, pkt)
484
485 #define dbg_addr_with_tgt(action, pkt_str, src, dst, target, pkt) \
486 do { \
487 NET_DBG("%s %s from %s to %s, target %s iface %p/%d", \
488 action, \
489 pkt_str, \
490 log_strdup(net_sprint_ipv6_addr(src)), \
491 log_strdup(net_sprint_ipv6_addr(dst)), \
492 log_strdup(net_sprint_ipv6_addr(target)), \
493 net_pkt_iface(pkt), \
494 net_if_get_by_iface(net_pkt_iface(pkt))); \
495 } while (0)
496
497 #define dbg_addr_recv_tgt(pkt_str, src, dst, tgt, pkt) \
498 dbg_addr_with_tgt("Received", pkt_str, src, dst, tgt, pkt)
499
500 #define dbg_addr_sent_tgt(pkt_str, src, dst, tgt, pkt) \
501 dbg_addr_with_tgt("Sent", pkt_str, src, dst, tgt, pkt)
502
ipv6_nd_remove_old_stale_nbr(void)503 static void ipv6_nd_remove_old_stale_nbr(void)
504 {
505 struct net_nbr *nbr = NULL;
506 struct net_ipv6_nbr_data *data = NULL;
507 int nbr_idx = -1;
508 uint32_t oldest = UINT32_MAX;
509 int i;
510
511 k_sem_take(&nbr_lock, K_FOREVER);
512
513 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
514 nbr = get_nbr(i);
515 if (!nbr || !nbr->ref) {
516 continue;
517 }
518
519 data = net_ipv6_nbr_data(nbr);
520 if (!data || data->is_router ||
521 data->state != NET_IPV6_NBR_STATE_STALE) {
522 continue;
523 }
524
525 if (nbr_idx == -1) {
526 nbr_idx = i;
527 oldest = data->stale_counter;
528 continue;
529 }
530
531 if (oldest == MIN(oldest, data->stale_counter)) {
532 continue;
533 }
534
535 nbr_idx = i;
536 oldest = data->stale_counter;
537 }
538
539 if (nbr_idx != -1) {
540 nbr = get_nbr(nbr_idx);
541 if (!nbr) {
542 return;
543 }
544
545 net_ipv6_nbr_rm(nbr->iface,
546 &net_ipv6_nbr_data(nbr)->addr);
547 }
548
549 k_sem_give(&nbr_lock);
550 }
551
add_nbr(struct net_if * iface,const struct in6_addr * addr,bool is_router,enum net_ipv6_nbr_state state)552 static struct net_nbr *add_nbr(struct net_if *iface,
553 const struct in6_addr *addr,
554 bool is_router,
555 enum net_ipv6_nbr_state state)
556 {
557 struct net_nbr *nbr;
558
559 nbr = nbr_lookup(&net_neighbor.table, iface, addr);
560 if (nbr) {
561 return nbr;
562 }
563
564 nbr = nbr_new(iface, addr, is_router, state);
565 if (nbr) {
566 return nbr;
567 }
568
569 /* Check if there are any stale neighbors, delete the oldest
570 * one and try to add new neighbor.
571 */
572 ipv6_nd_remove_old_stale_nbr();
573
574 nbr = nbr_new(iface, addr, is_router, state);
575 if (!nbr) {
576 return NULL;
577 }
578
579 return nbr;
580 }
581
net_ipv6_nbr_add(struct net_if * iface,const struct in6_addr * addr,const struct net_linkaddr * lladdr,bool is_router,enum net_ipv6_nbr_state state)582 struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
583 const struct in6_addr *addr,
584 const struct net_linkaddr *lladdr,
585 bool is_router,
586 enum net_ipv6_nbr_state state)
587 {
588 struct net_nbr *nbr;
589 int ret;
590 #if defined(CONFIG_NET_MGMT_EVENT_INFO)
591 struct net_event_ipv6_nbr info;
592 #endif
593
594 nbr = add_nbr(iface, addr, is_router, state);
595 if (!nbr) {
596 NET_ERR("Could not add router neighbor %s [%s]",
597 log_strdup(net_sprint_ipv6_addr(addr)),
598 log_strdup(net_sprint_ll_addr(lladdr->addr,
599 lladdr->len)));
600 return NULL;
601 }
602
603 if (net_nbr_link(nbr, iface, lladdr) == -EALREADY &&
604 net_ipv6_nbr_data(nbr)->state != NET_IPV6_NBR_STATE_STATIC) {
605 /* Update the lladdr if the node was already known */
606 struct net_linkaddr_storage *cached_lladdr;
607
608 cached_lladdr = net_nbr_get_lladdr(nbr->idx);
609
610 if (memcmp(cached_lladdr->addr, lladdr->addr, lladdr->len)) {
611 dbg_update_neighbor_lladdr(lladdr, cached_lladdr, addr);
612
613 net_linkaddr_set(cached_lladdr, lladdr->addr,
614 lladdr->len);
615
616 ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
617 } else if (net_ipv6_nbr_data(nbr)->state ==
618 NET_IPV6_NBR_STATE_INCOMPLETE) {
619 ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
620 }
621 }
622
623 if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_INCOMPLETE) {
624 /* Send NS so that we can verify that the neighbor is
625 * reachable.
626 */
627 ret = net_ipv6_send_ns(iface, NULL, NULL, NULL, addr, false);
628 if (ret < 0) {
629 NET_DBG("Cannot send NS (%d)", ret);
630 }
631 }
632
633 NET_DBG("[%d] nbr %p state %d router %d IPv6 %s ll %s iface %p/%d",
634 nbr->idx, nbr, state, is_router,
635 log_strdup(net_sprint_ipv6_addr(addr)),
636 log_strdup(net_sprint_ll_addr(lladdr->addr, lladdr->len)),
637 nbr->iface, net_if_get_by_iface(nbr->iface));
638
639 #if defined(CONFIG_NET_MGMT_EVENT_INFO)
640 info.idx = nbr->idx;
641 net_ipaddr_copy(&info.addr, addr);
642 net_mgmt_event_notify_with_info(NET_EVENT_IPV6_NBR_ADD,
643 iface, (void *) &info,
644 sizeof(struct net_event_ipv6_nbr));
645 #else
646 net_mgmt_event_notify(NET_EVENT_IPV6_NBR_ADD, iface);
647 #endif
648
649 return nbr;
650 }
651
net_neighbor_data_remove(struct net_nbr * nbr)652 void net_neighbor_data_remove(struct net_nbr *nbr)
653 {
654 NET_DBG("Neighbor %p removed", nbr);
655
656 return;
657 }
658
net_neighbor_table_clear(struct net_nbr_table * table)659 void net_neighbor_table_clear(struct net_nbr_table *table)
660 {
661 NET_DBG("Neighbor table %p cleared", table);
662 }
663
net_ipv6_nbr_lookup_by_index(struct net_if * iface,uint8_t idx)664 struct in6_addr *net_ipv6_nbr_lookup_by_index(struct net_if *iface,
665 uint8_t idx)
666 {
667 int i;
668
669 if (idx == NET_NBR_LLADDR_UNKNOWN) {
670 return NULL;
671 }
672
673 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
674 struct net_nbr *nbr = get_nbr(i);
675
676 if (!nbr->ref) {
677 continue;
678 }
679
680 if (iface && nbr->iface != iface) {
681 continue;
682 }
683
684 if (nbr->idx == idx) {
685 return &net_ipv6_nbr_data(nbr)->addr;
686 }
687 }
688
689 return NULL;
690 }
691 #else
net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state)692 const char *net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state)
693 {
694 return "<unknown state>";
695 }
696 #endif /* CONFIG_NET_IPV6_NBR_CACHE */
697
698 #if defined(CONFIG_NET_IPV6_DAD)
net_ipv6_start_dad(struct net_if * iface,struct net_if_addr * ifaddr)699 int net_ipv6_start_dad(struct net_if *iface, struct net_if_addr *ifaddr)
700 {
701 return net_ipv6_send_ns(iface, NULL, NULL, NULL,
702 &ifaddr->address.in6_addr, true);
703 }
704
dad_failed(struct net_if * iface,struct in6_addr * addr)705 static inline bool dad_failed(struct net_if *iface, struct in6_addr *addr)
706 {
707 if (net_ipv6_is_ll_addr(addr)) {
708 NET_ERR("DAD failed, no ll IPv6 address!");
709 return false;
710 }
711
712 net_if_ipv6_dad_failed(iface, addr);
713
714 return true;
715 }
716 #endif /* CONFIG_NET_IPV6_DAD */
717
718 #if defined(CONFIG_NET_IPV6_NBR_CACHE)
check_route(struct net_if * iface,struct in6_addr * dst,bool * try_route)719 static struct in6_addr *check_route(struct net_if *iface,
720 struct in6_addr *dst,
721 bool *try_route)
722 {
723 struct in6_addr *nexthop = NULL;
724 struct net_route_entry *route;
725 struct net_if_router *router;
726
727 route = net_route_lookup(iface, dst);
728 if (route) {
729 nexthop = net_route_get_nexthop(route);
730
731 NET_DBG("Route %p nexthop %s iface %p/%d",
732 route,
733 nexthop ? log_strdup(net_sprint_ipv6_addr(nexthop)) :
734 "<unknown>",
735 iface, net_if_get_by_iface(iface));
736
737 if (!nexthop) {
738 net_route_del(route);
739
740 NET_DBG("No route to host %s",
741 log_strdup(net_sprint_ipv6_addr(dst)));
742
743 return NULL;
744 }
745 } else {
746 /* No specific route to this host, use the default
747 * route instead.
748 */
749 router = net_if_ipv6_router_find_default(NULL, dst);
750 if (!router) {
751 NET_DBG("No default route to %s",
752 log_strdup(net_sprint_ipv6_addr(dst)));
753
754 /* Try to send the packet anyway */
755 nexthop = dst;
756 if (try_route) {
757 *try_route = true;
758 }
759
760 return nexthop;
761 }
762
763 nexthop = &router->address.in6_addr;
764
765 NET_DBG("Router %p nexthop %s", router,
766 log_strdup(net_sprint_ipv6_addr(nexthop)));
767 }
768
769 return nexthop;
770 }
771
net_ipv6_prepare_for_send(struct net_pkt * pkt)772 enum net_verdict net_ipv6_prepare_for_send(struct net_pkt *pkt)
773 {
774 NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
775 struct in6_addr *nexthop = NULL;
776 struct net_if *iface = NULL;
777 struct net_ipv6_hdr *ip_hdr;
778 struct net_nbr *nbr;
779 int ret;
780
781 NET_ASSERT(pkt && pkt->buffer);
782
783 ip_hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
784 if (!ip_hdr) {
785 return NET_DROP;
786 }
787
788 #if defined(CONFIG_NET_IPV6_FRAGMENT)
789 /* If we have already fragmented the packet, the fragment id will
790 * contain a proper value and we can skip other checks.
791 */
792 if (net_pkt_ipv6_fragment_id(pkt) == 0U) {
793 uint16_t mtu = net_if_get_mtu(net_pkt_iface(pkt));
794 size_t pkt_len = net_pkt_get_len(pkt);
795
796 mtu = MAX(NET_IPV6_MTU, mtu);
797 if (mtu < pkt_len) {
798 ret = net_ipv6_send_fragmented_pkt(net_pkt_iface(pkt),
799 pkt, pkt_len);
800 if (ret < 0) {
801 NET_DBG("Cannot fragment IPv6 pkt (%d)", ret);
802
803 if (ret == -ENOMEM) {
804 /* Try to send the packet if we could
805 * not allocate enough network packets
806 * and hope the original large packet
807 * can be sent ok.
808 */
809 goto ignore_frag_error;
810 }
811 }
812
813 /* We "fake" the sending of the packet here so that
814 * tcp.c:tcp_retry_expired() will increase the ref
815 * count when re-sending the packet. This is crucial
816 * thing to do here and will cause free memory access
817 * if not done.
818 */
819 if (IS_ENABLED(CONFIG_NET_TCP)) {
820 net_pkt_set_sent(pkt, true);
821 }
822
823 /* We need to unref here because we simulate the packet
824 * sending.
825 */
826 net_pkt_unref(pkt);
827
828 /* No need to continue with the sending as the packet
829 * is now split and its fragments will be sent
830 * separately to network.
831 */
832 return NET_CONTINUE;
833 }
834 }
835 ignore_frag_error:
836 #endif /* CONFIG_NET_IPV6_FRAGMENT */
837
838 /* If the IPv6 destination address is not link local, then try to get
839 * the next hop from routing table if we have multi interface routing
840 * enabled. The reason for this is that the neighbor cache will not
841 * contain public IPv6 address information so in that case we should
842 * not enter this branch.
843 */
844 if ((net_pkt_lladdr_dst(pkt)->addr &&
845 ((IS_ENABLED(CONFIG_NET_ROUTING) &&
846 net_ipv6_is_ll_addr(&ip_hdr->dst)) ||
847 !IS_ENABLED(CONFIG_NET_ROUTING))) ||
848 net_ipv6_is_addr_mcast(&ip_hdr->dst) ||
849 /* Workaround Linux bug, see:
850 * https://github.com/zephyrproject-rtos/zephyr/issues/3111
851 */
852 net_if_flag_is_set(net_pkt_iface(pkt),
853 NET_IF_POINTOPOINT)) {
854 return NET_OK;
855 }
856
857 if (net_if_ipv6_addr_onlink(&iface, &ip_hdr->dst)) {
858 nexthop = &ip_hdr->dst;
859 net_pkt_set_iface(pkt, iface);
860 } else {
861 /* We need to figure out where the destination
862 * host is located.
863 */
864 bool try_route = false;
865
866 nexthop = check_route(NULL, &ip_hdr->dst, &try_route);
867 if (!nexthop) {
868 return NET_DROP;
869 }
870
871 if (try_route) {
872 goto try_send;
873 }
874 }
875
876 if (!iface) {
877 /* This means that the dst was not onlink, so try to
878 * figure out the interface using nexthop instead.
879 */
880 if (net_if_ipv6_addr_onlink(&iface, nexthop)) {
881 net_pkt_set_iface(pkt, iface);
882 } else {
883 /* nexthop might be the nbr list, e.g. a link-local
884 * address of a connected peer.
885 */
886 nbr = net_ipv6_nbr_lookup(NULL, nexthop);
887 if (nbr) {
888 iface = nbr->iface;
889 net_pkt_set_iface(pkt, iface);
890 } else {
891 iface = net_pkt_iface(pkt);
892 }
893 }
894
895 /* If the above check returns null, we try to send
896 * the packet and hope for the best.
897 */
898 }
899
900 try_send:
901 nbr = nbr_lookup(&net_neighbor.table, iface, nexthop);
902
903 NET_DBG("Neighbor lookup %p (%d) iface %p/%d addr %s state %s", nbr,
904 nbr ? nbr->idx : NET_NBR_LLADDR_UNKNOWN,
905 iface, net_if_get_by_iface(iface),
906 log_strdup(net_sprint_ipv6_addr(nexthop)),
907 nbr ? net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state) :
908 "-");
909
910 if (nbr && nbr->idx != NET_NBR_LLADDR_UNKNOWN) {
911 struct net_linkaddr_storage *lladdr;
912
913 lladdr = net_nbr_get_lladdr(nbr->idx);
914
915 net_pkt_lladdr_dst(pkt)->addr = lladdr->addr;
916 net_pkt_lladdr_dst(pkt)->len = lladdr->len;
917
918 NET_DBG("Neighbor %p addr %s", nbr,
919 log_strdup(net_sprint_ll_addr(lladdr->addr,
920 lladdr->len)));
921
922 /* Start the NUD if we are in STALE state.
923 * See RFC 4861 ch 7.3.3 for details.
924 */
925 #if defined(CONFIG_NET_IPV6_ND)
926 if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_STALE) {
927 ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_DELAY);
928
929 ipv6_nd_restart_reachable_timer(nbr,
930 DELAY_FIRST_PROBE_TIME);
931 }
932 #endif
933 return NET_OK;
934 }
935
936 #if defined(CONFIG_NET_IPV6_ND)
937 /* We need to send NS and wait for NA before sending the packet. */
938 ret = net_ipv6_send_ns(net_pkt_iface(pkt), pkt,
939 &ip_hdr->src, NULL, nexthop, false);
940 if (ret < 0) {
941 /* In case of an error, the NS send function will unref
942 * the pkt.
943 */
944 NET_DBG("Cannot send NS (%d) iface %p/%d",
945 ret, net_pkt_iface(pkt),
946 net_if_get_by_iface(net_pkt_iface(pkt)));
947 }
948
949 NET_DBG("pkt %p (buffer %p) will be sent later to iface %p/%d",
950 pkt, pkt->buffer, net_pkt_iface(pkt),
951 net_if_get_by_iface(net_pkt_iface(pkt)));
952
953 return NET_CONTINUE;
954 #else
955 ARG_UNUSED(ret);
956
957 NET_DBG("pkt %p (buffer %p) cannot be sent to iface %p/%d, "
958 "dropping it.", pkt, pkt->buffer,
959 net_pkt_iface(pkt), net_if_get_by_iface(net_pkt_iface(pkt)));
960
961 return NET_DROP;
962 #endif /* CONFIG_NET_IPV6_ND */
963 }
964
net_ipv6_nbr_lookup(struct net_if * iface,struct in6_addr * addr)965 struct net_nbr *net_ipv6_nbr_lookup(struct net_if *iface,
966 struct in6_addr *addr)
967 {
968 return nbr_lookup(&net_neighbor.table, iface, addr);
969 }
970
net_ipv6_get_nbr(struct net_if * iface,uint8_t idx)971 struct net_nbr *net_ipv6_get_nbr(struct net_if *iface, uint8_t idx)
972 {
973 int i;
974
975 if (idx == NET_NBR_LLADDR_UNKNOWN) {
976 return NULL;
977 }
978
979 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
980 struct net_nbr *nbr = get_nbr(i);
981
982 if (nbr->ref) {
983 if (iface && nbr->iface != iface) {
984 continue;
985 }
986
987 if (nbr->idx == idx) {
988 return nbr;
989 }
990 }
991 }
992
993 return NULL;
994 }
995
get_llao_len(struct net_if * iface)996 static inline uint8_t get_llao_len(struct net_if *iface)
997 {
998 uint8_t total_len = net_if_get_link_addr(iface)->len +
999 sizeof(struct net_icmpv6_nd_opt_hdr);
1000
1001 return ROUND_UP(total_len, 8U);
1002 }
1003
set_llao(struct net_pkt * pkt,struct net_linkaddr * lladdr,uint8_t llao_len,uint8_t type)1004 static inline bool set_llao(struct net_pkt *pkt,
1005 struct net_linkaddr *lladdr,
1006 uint8_t llao_len, uint8_t type)
1007 {
1008 struct net_icmpv6_nd_opt_hdr opt_hdr = {
1009 .type = type,
1010 .len = llao_len >> 3,
1011 };
1012
1013 if (net_pkt_write(pkt, &opt_hdr,
1014 sizeof(struct net_icmpv6_nd_opt_hdr)) ||
1015 net_pkt_write(pkt, lladdr->addr, lladdr->len) ||
1016 net_pkt_memset(pkt, 0, llao_len - lladdr->len - 2)) {
1017 return false;
1018 }
1019
1020 return true;
1021 }
1022
read_llao(struct net_pkt * pkt,uint8_t len,struct net_linkaddr_storage * llstorage)1023 static bool read_llao(struct net_pkt *pkt,
1024 uint8_t len,
1025 struct net_linkaddr_storage *llstorage)
1026 {
1027 uint8_t padding;
1028
1029 llstorage->len = NET_LINK_ADDR_MAX_LENGTH;
1030 if (net_pkt_lladdr_src(pkt)->len < llstorage->len) {
1031 llstorage->len = net_pkt_lladdr_src(pkt)->len;
1032 }
1033
1034 if (net_pkt_read(pkt, llstorage->addr, llstorage->len)) {
1035 return false;
1036 }
1037
1038 padding = len * 8U - 2 - llstorage->len;
1039 if (padding) {
1040 if (net_pkt_skip(pkt, padding)) {
1041 return false;
1042 }
1043 }
1044
1045 return true;
1046 }
1047
net_ipv6_send_na(struct net_if * iface,const struct in6_addr * src,const struct in6_addr * dst,const struct in6_addr * tgt,uint8_t flags)1048 int net_ipv6_send_na(struct net_if *iface, const struct in6_addr *src,
1049 const struct in6_addr *dst, const struct in6_addr *tgt,
1050 uint8_t flags)
1051 {
1052 NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(na_access,
1053 struct net_icmpv6_na_hdr);
1054 int ret = -ENOBUFS;
1055 struct net_icmpv6_na_hdr *na_hdr;
1056 struct net_pkt *pkt;
1057 uint8_t llao_len;
1058
1059 llao_len = get_llao_len(iface);
1060
1061 pkt = net_pkt_alloc_with_buffer(iface,
1062 sizeof(struct net_icmpv6_na_hdr) +
1063 llao_len,
1064 AF_INET6, IPPROTO_ICMPV6,
1065 ND_NET_BUF_TIMEOUT);
1066 if (!pkt) {
1067 return -ENOMEM;
1068 }
1069
1070 net_pkt_set_ipv6_hop_limit(pkt, NET_IPV6_ND_HOP_LIMIT);
1071
1072 if (net_ipv6_create(pkt, src, dst) ||
1073 net_icmpv6_create(pkt, NET_ICMPV6_NA, 0)) {
1074 goto drop;
1075 }
1076
1077 na_hdr = (struct net_icmpv6_na_hdr *)net_pkt_get_data(pkt, &na_access);
1078 if (!na_hdr) {
1079 goto drop;
1080 }
1081
1082 /* Let's make sure reserved part is full of 0 */
1083 memset(na_hdr, 0, sizeof(struct net_icmpv6_na_hdr));
1084
1085 na_hdr->flags = flags;
1086 net_ipaddr_copy(&na_hdr->tgt, tgt);
1087
1088 if (net_pkt_set_data(pkt, &na_access)) {
1089 goto drop;
1090 }
1091
1092 if (!set_llao(pkt, net_if_get_link_addr(iface),
1093 llao_len, NET_ICMPV6_ND_OPT_TLLAO)) {
1094 goto drop;
1095 }
1096
1097 net_pkt_cursor_init(pkt);
1098 net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
1099
1100 dbg_addr_sent_tgt("Neighbor Advertisement", src, dst, &na_hdr->tgt,
1101 pkt);
1102
1103 if (net_send_data(pkt) < 0) {
1104 net_stats_update_ipv6_nd_drop(iface);
1105 ret = -EINVAL;
1106
1107 goto drop;
1108 }
1109
1110 net_stats_update_ipv6_nd_sent(iface);
1111
1112 return 0;
1113
1114 drop:
1115 net_pkt_unref(pkt);
1116
1117 return ret;
1118 }
1119
ns_routing_info(struct net_pkt * pkt,struct in6_addr * nexthop,struct in6_addr * tgt)1120 static void ns_routing_info(struct net_pkt *pkt,
1121 struct in6_addr *nexthop,
1122 struct in6_addr *tgt)
1123 {
1124 if (CONFIG_NET_IPV6_LOG_LEVEL >= LOG_LEVEL_DBG) {
1125 char out[NET_IPV6_ADDR_LEN];
1126
1127 snprintk(out, sizeof(out), "%s",
1128 net_sprint_ipv6_addr(nexthop));
1129
1130 if (net_ipv6_addr_cmp(nexthop, tgt)) {
1131 NET_DBG("Routing to %s iface %p/%d",
1132 log_strdup(out),
1133 net_pkt_iface(pkt),
1134 net_if_get_by_iface(net_pkt_iface(pkt)));
1135 } else {
1136 NET_DBG("Routing to %s via %s iface %p/%d",
1137 log_strdup(net_sprint_ipv6_addr(tgt)),
1138 log_strdup(out),
1139 net_pkt_iface(pkt),
1140 net_if_get_by_iface(net_pkt_iface(pkt)));
1141 }
1142 }
1143 }
1144
handle_ns_input(struct net_pkt * pkt,struct net_ipv6_hdr * ip_hdr,struct net_icmp_hdr * icmp_hdr)1145 static enum net_verdict handle_ns_input(struct net_pkt *pkt,
1146 struct net_ipv6_hdr *ip_hdr,
1147 struct net_icmp_hdr *icmp_hdr)
1148 {
1149 NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ns_access,
1150 struct net_icmpv6_ns_hdr);
1151 NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr);
1152 uint16_t length = net_pkt_get_len(pkt);
1153 uint8_t flags = 0U;
1154 bool routing = false;
1155 struct net_icmpv6_nd_opt_hdr *nd_opt_hdr;
1156 struct net_icmpv6_ns_hdr *ns_hdr;
1157 struct net_if_addr *ifaddr;
1158 const struct in6_addr *na_src;
1159 const struct in6_addr *na_dst;
1160 struct in6_addr *tgt;
1161 struct net_linkaddr_storage src_lladdr_s;
1162 struct net_linkaddr src_lladdr;
1163
1164 src_lladdr.len = 0;
1165
1166 ns_hdr = (struct net_icmpv6_ns_hdr *)net_pkt_get_data(pkt, &ns_access);
1167 if (!ns_hdr) {
1168 NET_ERR("DROP: NULL NS header");
1169 goto drop;
1170 }
1171
1172 dbg_addr_recv_tgt("Neighbor Solicitation",
1173 &ip_hdr->src, &ip_hdr->dst, &ns_hdr->tgt, pkt);
1174
1175 net_stats_update_ipv6_nd_recv(net_pkt_iface(pkt));
1176
1177 if (((length < (sizeof(struct net_ipv6_hdr) +
1178 sizeof(struct net_icmp_hdr) +
1179 sizeof(struct net_icmpv6_ns_hdr))) ||
1180 (ip_hdr->hop_limit != NET_IPV6_ND_HOP_LIMIT)) &&
1181 (net_ipv6_is_addr_mcast(&ns_hdr->tgt) && icmp_hdr->code != 0U)) {
1182 goto drop;
1183 }
1184
1185 net_pkt_acknowledge_data(pkt, &ns_access);
1186
1187 net_pkt_set_ipv6_ext_opt_len(pkt, sizeof(struct net_icmpv6_ns_hdr));
1188 length -= (sizeof(struct net_ipv6_hdr) + sizeof(struct net_icmp_hdr));
1189
1190 nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
1191 net_pkt_get_data(pkt, &nd_access);
1192
1193 while (nd_opt_hdr && nd_opt_hdr->len > 0 &&
1194 net_pkt_ipv6_ext_opt_len(pkt) < length) {
1195 uint8_t prev_opt_len;
1196
1197 net_pkt_acknowledge_data(pkt, &nd_access);
1198
1199 switch (nd_opt_hdr->type) {
1200 case NET_ICMPV6_ND_OPT_SLLAO:
1201 if (net_ipv6_is_addr_unspecified(&ip_hdr->src)) {
1202 goto drop;
1203 }
1204
1205 if (!read_llao(pkt, nd_opt_hdr->len, &src_lladdr_s)) {
1206 NET_ERR("DROP: failed to read LLAO");
1207 goto drop;
1208 }
1209
1210 src_lladdr.len = src_lladdr_s.len;
1211 src_lladdr.addr = src_lladdr_s.addr;
1212
1213 break;
1214 default:
1215 NET_DBG("Unknown ND option 0x%x", nd_opt_hdr->type);
1216 break;
1217 }
1218
1219 prev_opt_len = net_pkt_ipv6_ext_opt_len(pkt);
1220
1221 net_pkt_set_ipv6_ext_opt_len(pkt,
1222 net_pkt_ipv6_ext_opt_len(pkt) +
1223 (nd_opt_hdr->len << 3));
1224
1225 if (prev_opt_len >= net_pkt_ipv6_ext_opt_len(pkt)) {
1226 NET_ERR("DROP: Corrupted NS message");
1227 goto drop;
1228 }
1229
1230 nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
1231 net_pkt_get_data(pkt, &nd_access);
1232 }
1233
1234 if (IS_ENABLED(CONFIG_NET_ROUTING)) {
1235 ifaddr = net_if_ipv6_addr_lookup(&ns_hdr->tgt, NULL);
1236 } else {
1237 ifaddr = net_if_ipv6_addr_lookup_by_iface(net_pkt_iface(pkt),
1238 &ns_hdr->tgt);
1239 }
1240
1241 if (!ifaddr) {
1242 if (IS_ENABLED(CONFIG_NET_ROUTING)) {
1243 struct in6_addr *nexthop;
1244
1245 nexthop = check_route(NULL, &ns_hdr->tgt, NULL);
1246 if (nexthop) {
1247 ns_routing_info(pkt, nexthop, &ns_hdr->tgt);
1248 na_dst = &ip_hdr->dst;
1249 /* Note that the target is not the address of
1250 * the "nethop" as that is a link-local address
1251 * which is not routable.
1252 */
1253 tgt = &ns_hdr->tgt;
1254
1255 /* Source address must be one of our real
1256 * interface address where the packet was
1257 * received.
1258 */
1259 na_src = net_if_ipv6_select_src_addr(
1260 net_pkt_iface(pkt), &ip_hdr->src);
1261 if (!na_src) {
1262 NET_DBG("DROP: No interface address "
1263 "for dst %s iface %p/%d",
1264 log_strdup(
1265 net_sprint_ipv6_addr(
1266 &ip_hdr->src)),
1267 net_pkt_iface(pkt),
1268 net_if_get_by_iface(
1269 net_pkt_iface(pkt)));
1270 goto drop;
1271 }
1272
1273 routing = true;
1274 goto nexthop_found;
1275 }
1276 }
1277
1278 NET_DBG("DROP: No such interface address %s",
1279 log_strdup(net_sprint_ipv6_addr(&ns_hdr->tgt)));
1280 goto drop;
1281 } else {
1282 tgt = &ifaddr->address.in6_addr;
1283 na_src = &ip_hdr->dst;
1284 }
1285
1286 nexthop_found:
1287
1288 #if !defined(CONFIG_NET_IPV6_DAD)
1289 if (net_ipv6_is_addr_unspecified(&ip_hdr->src)) {
1290 goto drop;
1291 }
1292
1293 #else /* CONFIG_NET_IPV6_DAD */
1294
1295 /* Do DAD */
1296 if (net_ipv6_is_addr_unspecified(&ip_hdr->src)) {
1297
1298 if (!net_ipv6_is_addr_solicited_node(&ip_hdr->dst)) {
1299 NET_DBG("DROP: Not solicited node addr %s",
1300 log_strdup(net_sprint_ipv6_addr(&ip_hdr->dst)));
1301 goto drop;
1302 }
1303
1304 if (ifaddr->addr_state == NET_ADDR_TENTATIVE) {
1305 NET_DBG("DROP: DAD failed for %s iface %p/%d",
1306 log_strdup(net_sprint_ipv6_addr(
1307 &ifaddr->address.in6_addr)),
1308 net_pkt_iface(pkt),
1309 net_if_get_by_iface(net_pkt_iface(pkt)));
1310
1311 dad_failed(net_pkt_iface(pkt),
1312 &ifaddr->address.in6_addr);
1313 goto drop;
1314 }
1315
1316 /* We reuse the received packet for the NA addresses*/
1317 net_ipv6_addr_create_ll_allnodes_mcast(&ip_hdr->dst);
1318 net_ipaddr_copy(&ip_hdr->src,
1319 net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
1320 &ip_hdr->dst));
1321 na_src = &ip_hdr->src;
1322 na_dst = &ip_hdr->dst;
1323 flags = NET_ICMPV6_NA_FLAG_OVERRIDE;
1324 goto send_na;
1325 }
1326 #endif /* CONFIG_NET_IPV6_DAD */
1327
1328 if (net_ipv6_is_my_addr(&ip_hdr->src)) {
1329 NET_DBG("DROP: Duplicate IPv6 %s address",
1330 log_strdup(net_sprint_ipv6_addr(&ip_hdr->src)));
1331 goto drop;
1332 }
1333
1334 /* Address resolution */
1335 if (net_ipv6_is_addr_solicited_node(&ip_hdr->dst)) {
1336 na_src = &ns_hdr->tgt;
1337 na_dst = &ip_hdr->src;
1338 flags = NET_ICMPV6_NA_FLAG_SOLICITED |
1339 NET_ICMPV6_NA_FLAG_OVERRIDE;
1340 goto send_na;
1341 }
1342
1343 if (routing) {
1344 /* No need to do NUD here when the target is being routed. */
1345 goto send_na;
1346 }
1347
1348 /* Neighbor Unreachability Detection (NUD) */
1349 if (IS_ENABLED(CONFIG_NET_ROUTING)) {
1350 ifaddr = net_if_ipv6_addr_lookup(&ip_hdr->dst, NULL);
1351 } else {
1352 ifaddr = net_if_ipv6_addr_lookup_by_iface(net_pkt_iface(pkt),
1353 &ip_hdr->dst);
1354 }
1355
1356 if (ifaddr) {
1357 na_src = &ns_hdr->tgt;
1358 na_dst = &ip_hdr->src;
1359 tgt = &ifaddr->address.in6_addr;
1360 flags = NET_ICMPV6_NA_FLAG_SOLICITED |
1361 NET_ICMPV6_NA_FLAG_OVERRIDE;
1362 goto send_na;
1363 } else {
1364 NET_DBG("DROP: NUD failed");
1365 goto drop;
1366 }
1367
1368 send_na:
1369 if (src_lladdr.len) {
1370 if (!net_ipv6_nbr_add(net_pkt_iface(pkt),
1371 &ip_hdr->src,
1372 &src_lladdr, false,
1373 NET_IPV6_NBR_STATE_INCOMPLETE)) {
1374 goto drop;
1375 }
1376 }
1377
1378 if (!net_ipv6_send_na(net_pkt_iface(pkt), na_src,
1379 na_dst, tgt, flags)) {
1380 net_pkt_unref(pkt);
1381 return NET_OK;
1382 }
1383
1384 NET_DBG("DROP: Cannot send NA");
1385
1386 return NET_DROP;
1387
1388 drop:
1389 net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt));
1390
1391 return NET_DROP;
1392 }
1393 #endif /* CONFIG_NET_IPV6_NBR_CACHE */
1394
1395 #if defined(CONFIG_NET_IPV6_ND)
ipv6_nd_restart_reachable_timer(struct net_nbr * nbr,int64_t time)1396 static void ipv6_nd_restart_reachable_timer(struct net_nbr *nbr, int64_t time)
1397 {
1398 int64_t remaining;
1399
1400 if (nbr) {
1401 net_ipv6_nbr_data(nbr)->reachable = k_uptime_get();
1402 net_ipv6_nbr_data(nbr)->reachable_timeout = time;
1403 }
1404
1405 remaining = k_ticks_to_ms_ceil32(
1406 k_work_delayable_remaining_get(&ipv6_nd_reachable_timer));
1407 if (!remaining || remaining > time) {
1408 k_work_reschedule(&ipv6_nd_reachable_timer, K_MSEC(time));
1409 }
1410 }
1411
ipv6_nd_reachable_timeout(struct k_work * work)1412 static void ipv6_nd_reachable_timeout(struct k_work *work)
1413 {
1414 int64_t current = k_uptime_get();
1415 struct net_nbr *nbr = NULL;
1416 struct net_ipv6_nbr_data *data = NULL;
1417 int ret;
1418 int i;
1419
1420 for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
1421 int64_t remaining;
1422
1423 nbr = get_nbr(i);
1424 if (!nbr || !nbr->ref) {
1425 continue;
1426 }
1427
1428 data = net_ipv6_nbr_data(nbr);
1429 if (!data) {
1430 continue;
1431 }
1432
1433 if (!data->reachable) {
1434 continue;
1435 }
1436
1437 remaining = data->reachable + data->reachable_timeout - current;
1438 if (remaining > 0) {
1439 ipv6_nd_restart_reachable_timer(NULL, remaining);
1440 continue;
1441 }
1442
1443 data->reachable = 0;
1444
1445 switch (data->state) {
1446 case NET_IPV6_NBR_STATE_STATIC:
1447 NET_ASSERT(false, "Static entry shall never timeout");
1448 break;
1449
1450 case NET_IPV6_NBR_STATE_INCOMPLETE:
1451 if (data->ns_count >= MAX_MULTICAST_SOLICIT) {
1452 net_ipv6_nbr_rm(nbr->iface, &data->addr);
1453 } else {
1454 data->ns_count++;
1455
1456 NET_DBG("nbr %p incomplete count %u", nbr,
1457 data->ns_count);
1458
1459 ret = net_ipv6_send_ns(nbr->iface, NULL, NULL,
1460 NULL, &data->addr,
1461 false);
1462 if (ret < 0) {
1463 NET_DBG("Cannot send NS (%d)", ret);
1464 }
1465 }
1466 break;
1467
1468 case NET_IPV6_NBR_STATE_REACHABLE:
1469 data->state = NET_IPV6_NBR_STATE_STALE;
1470
1471 NET_DBG("nbr %p moving %s state to STALE (%d)",
1472 nbr,
1473 log_strdup(net_sprint_ipv6_addr(&data->addr)),
1474 data->state);
1475 break;
1476
1477 case NET_IPV6_NBR_STATE_STALE:
1478 NET_DBG("nbr %p removing stale address %s",
1479 nbr,
1480 log_strdup(net_sprint_ipv6_addr(&data->addr)));
1481 net_ipv6_nbr_rm(nbr->iface, &data->addr);
1482 break;
1483
1484 case NET_IPV6_NBR_STATE_DELAY:
1485 data->state = NET_IPV6_NBR_STATE_PROBE;
1486 data->ns_count = 0U;
1487
1488 NET_DBG("nbr %p moving %s state to PROBE (%d)",
1489 nbr,
1490 log_strdup(net_sprint_ipv6_addr(&data->addr)),
1491 data->state);
1492
1493 /* Intentionally continuing to probe state */
1494 __fallthrough;
1495
1496 case NET_IPV6_NBR_STATE_PROBE:
1497 if (data->ns_count >= MAX_UNICAST_SOLICIT) {
1498 net_ipv6_nbr_rm(nbr->iface, &data->addr);
1499 } else {
1500 data->ns_count++;
1501
1502 NET_DBG("nbr %p probe count %u", nbr,
1503 data->ns_count);
1504
1505 ret = net_ipv6_send_ns(nbr->iface, NULL, NULL,
1506 NULL, &data->addr,
1507 false);
1508 if (ret < 0) {
1509 NET_DBG("Cannot send NS (%d)", ret);
1510 }
1511
1512 ipv6_nd_restart_reachable_timer(nbr,
1513 RETRANS_TIMER);
1514 }
1515 break;
1516 }
1517 }
1518 }
1519
net_ipv6_nbr_set_reachable_timer(struct net_if * iface,struct net_nbr * nbr)1520 void net_ipv6_nbr_set_reachable_timer(struct net_if *iface,
1521 struct net_nbr *nbr)
1522 {
1523 uint32_t time;
1524
1525 time = net_if_ipv6_get_reachable_time(iface);
1526
1527 NET_ASSERT(time, "Zero reachable timeout!");
1528
1529 NET_DBG("Starting reachable timer nbr %p data %p time %d ms",
1530 nbr, net_ipv6_nbr_data(nbr), time);
1531
1532 ipv6_nd_restart_reachable_timer(nbr, time);
1533 }
1534 #endif /* CONFIG_NET_IPV6_ND */
1535
1536 #if defined(CONFIG_NET_IPV6_NBR_CACHE)
handle_na_neighbor(struct net_pkt * pkt,struct net_icmpv6_na_hdr * na_hdr,uint16_t tllao_offset)1537 static inline bool handle_na_neighbor(struct net_pkt *pkt,
1538 struct net_icmpv6_na_hdr *na_hdr,
1539 uint16_t tllao_offset)
1540 {
1541 struct net_linkaddr_storage lladdr = { 0 };
1542 bool lladdr_changed = false;
1543 struct net_linkaddr_storage *cached_lladdr;
1544 struct net_pkt *pending;
1545 struct net_nbr *nbr;
1546
1547 nbr = nbr_lookup(&net_neighbor.table, net_pkt_iface(pkt), &na_hdr->tgt);
1548
1549 NET_DBG("Neighbor lookup %p iface %p/%d addr %s", nbr,
1550 net_pkt_iface(pkt), net_if_get_by_iface(net_pkt_iface(pkt)),
1551 log_strdup(net_sprint_ipv6_addr(&na_hdr->tgt)));
1552
1553 if (!nbr) {
1554 nbr_print();
1555
1556 NET_DBG("No such neighbor found, msg discarded");
1557 return false;
1558 }
1559
1560 if (tllao_offset) {
1561 lladdr.len = net_pkt_lladdr_src(pkt)->len;
1562
1563 net_pkt_cursor_init(pkt);
1564
1565 if (net_pkt_skip(pkt, tllao_offset) ||
1566 net_pkt_read(pkt, lladdr.addr, lladdr.len)) {
1567 return false;
1568 }
1569 }
1570
1571 if (nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
1572 struct net_linkaddr nbr_lladdr;
1573
1574 if (!tllao_offset) {
1575 NET_DBG("No target link layer address.");
1576 return false;
1577 }
1578
1579 nbr_lladdr.len = lladdr.len;
1580 nbr_lladdr.addr = lladdr.addr;
1581
1582 if (net_nbr_link(nbr, net_pkt_iface(pkt), &nbr_lladdr)) {
1583 nbr_free(nbr);
1584 return false;
1585 }
1586
1587 NET_DBG("[%d] nbr %p state %d IPv6 %s ll %s",
1588 nbr->idx, nbr, net_ipv6_nbr_data(nbr)->state,
1589 log_strdup(net_sprint_ipv6_addr(&na_hdr->tgt)),
1590 log_strdup(net_sprint_ll_addr(nbr_lladdr.addr,
1591 nbr_lladdr.len)));
1592 }
1593
1594 cached_lladdr = net_nbr_get_lladdr(nbr->idx);
1595 if (!cached_lladdr) {
1596 NET_DBG("No lladdr but index defined");
1597 return false;
1598 }
1599
1600 if (tllao_offset) {
1601 lladdr_changed = memcmp(lladdr.addr,
1602 cached_lladdr->addr,
1603 cached_lladdr->len);
1604 }
1605
1606 /* Update the cached address if we do not yet known it */
1607 if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_INCOMPLETE) {
1608 if (!tllao_offset) {
1609 return false;
1610 }
1611
1612 if (lladdr_changed) {
1613 dbg_update_neighbor_lladdr_raw(lladdr.addr,
1614 cached_lladdr,
1615 &na_hdr->tgt);
1616
1617 net_linkaddr_set(cached_lladdr, lladdr.addr,
1618 cached_lladdr->len);
1619 }
1620
1621 if (na_hdr->flags & NET_ICMPV6_NA_FLAG_SOLICITED) {
1622 ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_REACHABLE);
1623 net_ipv6_nbr_data(nbr)->ns_count = 0U;
1624
1625 /* We might have active timer from PROBE */
1626 net_ipv6_nbr_data(nbr)->reachable = 0;
1627 net_ipv6_nbr_data(nbr)->reachable_timeout = 0;
1628
1629 net_ipv6_nbr_set_reachable_timer(net_pkt_iface(pkt),
1630 nbr);
1631 } else {
1632 ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
1633 }
1634
1635 net_ipv6_nbr_data(nbr)->is_router =
1636 (na_hdr->flags & NET_ICMPV6_NA_FLAG_ROUTER);
1637
1638 goto send_pending;
1639 }
1640
1641 /* We do not update the address if override bit is not set
1642 * and we have a valid address in the cache.
1643 */
1644 if (!(na_hdr->flags & NET_ICMPV6_NA_FLAG_OVERRIDE) && lladdr_changed) {
1645 if (net_ipv6_nbr_data(nbr)->state ==
1646 NET_IPV6_NBR_STATE_REACHABLE) {
1647 ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
1648 }
1649
1650 return false;
1651 }
1652
1653 if (na_hdr->flags & NET_ICMPV6_NA_FLAG_OVERRIDE ||
1654 (!(na_hdr->flags & NET_ICMPV6_NA_FLAG_OVERRIDE) &&
1655 tllao_offset && !lladdr_changed)) {
1656
1657 if (lladdr_changed) {
1658 dbg_update_neighbor_lladdr_raw(
1659 lladdr.addr, cached_lladdr, &na_hdr->tgt);
1660
1661 net_linkaddr_set(cached_lladdr, lladdr.addr,
1662 cached_lladdr->len);
1663 }
1664
1665 if (na_hdr->flags & NET_ICMPV6_NA_FLAG_SOLICITED) {
1666 ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_REACHABLE);
1667
1668 /* We might have active timer from PROBE */
1669 net_ipv6_nbr_data(nbr)->reachable = 0;
1670 net_ipv6_nbr_data(nbr)->reachable_timeout = 0;
1671
1672 net_ipv6_nbr_set_reachable_timer(net_pkt_iface(pkt),
1673 nbr);
1674 } else {
1675 if (lladdr_changed) {
1676 ipv6_nbr_set_state(nbr,
1677 NET_IPV6_NBR_STATE_STALE);
1678 }
1679 }
1680 }
1681
1682 if (net_ipv6_nbr_data(nbr)->is_router &&
1683 !(na_hdr->flags & NET_ICMPV6_NA_FLAG_ROUTER)) {
1684 /* Update the routing if the peer is no longer
1685 * a router.
1686 */
1687 /* FIXME */
1688 }
1689
1690 net_ipv6_nbr_data(nbr)->is_router =
1691 (na_hdr->flags & NET_ICMPV6_NA_FLAG_ROUTER);
1692
1693 send_pending:
1694 /* Next send any pending messages to the peer. */
1695 pending = net_ipv6_nbr_data(nbr)->pending;
1696 if (pending) {
1697 NET_DBG("Sending pending %p to lladdr %s", pending,
1698 log_strdup(net_sprint_ll_addr(cached_lladdr->addr,
1699 cached_lladdr->len)));
1700
1701 if (net_send_data(pending) < 0) {
1702 nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
1703 } else {
1704 net_ipv6_nbr_data(nbr)->pending = NULL;
1705 }
1706
1707 net_pkt_unref(pending);
1708 }
1709
1710 return true;
1711 }
1712
handle_na_input(struct net_pkt * pkt,struct net_ipv6_hdr * ip_hdr,struct net_icmp_hdr * icmp_hdr)1713 static enum net_verdict handle_na_input(struct net_pkt *pkt,
1714 struct net_ipv6_hdr *ip_hdr,
1715 struct net_icmp_hdr *icmp_hdr)
1716 {
1717 NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(na_access,
1718 struct net_icmpv6_na_hdr);
1719 NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr);
1720 uint16_t length = net_pkt_get_len(pkt);
1721 uint16_t tllao_offset = 0U;
1722 struct net_icmpv6_nd_opt_hdr *nd_opt_hdr;
1723 struct net_icmpv6_na_hdr *na_hdr;
1724 struct net_if_addr *ifaddr;
1725
1726 na_hdr = (struct net_icmpv6_na_hdr *)net_pkt_get_data(pkt, &na_access);
1727 if (!na_hdr) {
1728 NET_ERR("DROP: NULL NA header");
1729 goto drop;
1730 }
1731
1732 dbg_addr_recv_tgt("Neighbor Advertisement",
1733 &ip_hdr->src, &ip_hdr->dst, &na_hdr->tgt, pkt);
1734
1735 net_stats_update_ipv6_nd_recv(net_pkt_iface(pkt));
1736
1737 if (((length < (sizeof(struct net_ipv6_hdr) +
1738 sizeof(struct net_icmp_hdr) +
1739 sizeof(struct net_icmpv6_na_hdr) +
1740 sizeof(struct net_icmpv6_nd_opt_hdr))) ||
1741 (ip_hdr->hop_limit != NET_IPV6_ND_HOP_LIMIT) ||
1742 net_ipv6_is_addr_mcast(&na_hdr->tgt) ||
1743 (na_hdr->flags & NET_ICMPV6_NA_FLAG_SOLICITED &&
1744 net_ipv6_is_addr_mcast(&ip_hdr->dst))) &&
1745 (icmp_hdr->code != 0U)) {
1746 goto drop;
1747 }
1748
1749 net_pkt_acknowledge_data(pkt, &na_access);
1750
1751 net_pkt_set_ipv6_ext_opt_len(pkt, sizeof(struct net_icmpv6_na_hdr));
1752 length -= (sizeof(struct net_ipv6_hdr) + sizeof(struct net_icmp_hdr));
1753
1754 nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
1755 net_pkt_get_data(pkt, &nd_access);
1756
1757 while (nd_opt_hdr && nd_opt_hdr->len &&
1758 net_pkt_ipv6_ext_opt_len(pkt) < length) {
1759 uint8_t prev_opt_len;
1760
1761 switch (nd_opt_hdr->type) {
1762 case NET_ICMPV6_ND_OPT_TLLAO:
1763 tllao_offset = net_pkt_ip_hdr_len(pkt) +
1764 net_pkt_ipv6_ext_len(pkt) +
1765 sizeof(struct net_icmp_hdr) +
1766 net_pkt_ipv6_ext_opt_len(pkt) + 1 + 1;
1767 break;
1768
1769 default:
1770 NET_DBG("Unknown ND option 0x%x", nd_opt_hdr->type);
1771 break;
1772 }
1773
1774 prev_opt_len = net_pkt_ipv6_ext_opt_len(pkt);
1775
1776 net_pkt_set_ipv6_ext_opt_len(pkt,
1777 net_pkt_ipv6_ext_opt_len(pkt) +
1778 (nd_opt_hdr->len << 3));
1779
1780 if (prev_opt_len >= net_pkt_ipv6_ext_opt_len(pkt)) {
1781 NET_ERR("DROP: Corrupted NA message");
1782 goto drop;
1783 }
1784
1785 net_pkt_acknowledge_data(pkt, &nd_access);
1786 nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
1787 net_pkt_get_data(pkt, &nd_access);
1788 }
1789
1790 ifaddr = net_if_ipv6_addr_lookup_by_iface(net_pkt_iface(pkt),
1791 &na_hdr->tgt);
1792 if (ifaddr) {
1793 NET_DBG("Interface %p/%d already has address %s",
1794 net_pkt_iface(pkt),
1795 net_if_get_by_iface(net_pkt_iface(pkt)),
1796 log_strdup(net_sprint_ipv6_addr(&na_hdr->tgt)));
1797
1798 #if defined(CONFIG_NET_IPV6_DAD)
1799 if (ifaddr->addr_state == NET_ADDR_TENTATIVE) {
1800 dad_failed(net_pkt_iface(pkt), &na_hdr->tgt);
1801 }
1802 #endif /* CONFIG_NET_IPV6_DAD */
1803
1804 goto drop;
1805 }
1806
1807 if (!handle_na_neighbor(pkt, na_hdr, tllao_offset)) {
1808 goto drop;
1809 }
1810
1811 net_stats_update_ipv6_nd_sent(net_pkt_iface(pkt));
1812
1813 net_pkt_unref(pkt);
1814
1815 return NET_OK;
1816
1817 drop:
1818 net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt));
1819
1820 return NET_DROP;
1821 }
1822
net_ipv6_send_ns(struct net_if * iface,struct net_pkt * pending,const struct in6_addr * src,const struct in6_addr * dst,const struct in6_addr * tgt,bool is_my_address)1823 int net_ipv6_send_ns(struct net_if *iface,
1824 struct net_pkt *pending,
1825 const struct in6_addr *src,
1826 const struct in6_addr *dst,
1827 const struct in6_addr *tgt,
1828 bool is_my_address)
1829 {
1830 NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ns_access,
1831 struct net_icmpv6_ns_hdr);
1832 struct net_pkt *pkt = NULL;
1833 int ret = -ENOBUFS;
1834 struct net_icmpv6_ns_hdr *ns_hdr;
1835 struct in6_addr node_dst;
1836 struct net_nbr *nbr;
1837 uint8_t llao_len;
1838
1839 if (!dst) {
1840 net_ipv6_addr_create_solicited_node(tgt, &node_dst);
1841 dst = &node_dst;
1842 }
1843
1844 llao_len = get_llao_len(iface);
1845
1846 if (is_my_address) {
1847 src = net_ipv6_unspecified_address();
1848 llao_len = 0U;
1849 } else {
1850 if (!src) {
1851 src = net_if_ipv6_select_src_addr(iface, tgt);
1852 }
1853
1854 if (net_ipv6_is_addr_unspecified(src)) {
1855 NET_DBG("No source address for NS (tgt %s)",
1856 log_strdup(net_sprint_ipv6_addr(tgt)));
1857 ret = -EINVAL;
1858
1859 goto drop;
1860 }
1861 }
1862
1863 pkt = net_pkt_alloc_with_buffer(iface,
1864 sizeof(struct net_icmpv6_ns_hdr) +
1865 llao_len,
1866 AF_INET6, IPPROTO_ICMPV6,
1867 ND_NET_BUF_TIMEOUT);
1868 if (!pkt) {
1869 ret = -ENOMEM;
1870 goto drop;
1871 }
1872
1873 /* Avoid recursive loop with network packet capturing */
1874 if (IS_ENABLED(CONFIG_NET_CAPTURE) && pending) {
1875 net_pkt_set_captured(pkt, net_pkt_is_captured(pending));
1876 }
1877
1878 net_pkt_set_ipv6_hop_limit(pkt, NET_IPV6_ND_HOP_LIMIT);
1879
1880 if (net_ipv6_create(pkt, src, dst) ||
1881 net_icmpv6_create(pkt, NET_ICMPV6_NS, 0)) {
1882 goto drop;
1883 }
1884
1885 ns_hdr = (struct net_icmpv6_ns_hdr *)net_pkt_get_data(pkt, &ns_access);
1886 if (!ns_hdr) {
1887 goto drop;
1888 }
1889
1890 ns_hdr->reserved = 0U;
1891 net_ipaddr_copy(&ns_hdr->tgt, tgt);
1892
1893 if (net_pkt_set_data(pkt, &ns_access)) {
1894 goto drop;
1895 }
1896
1897 if (!is_my_address) {
1898 if (!set_llao(pkt, net_if_get_link_addr(iface),
1899 llao_len, NET_ICMPV6_ND_OPT_SLLAO)) {
1900 goto drop;
1901 }
1902 }
1903
1904 net_pkt_cursor_init(pkt);
1905 net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
1906
1907 nbr = add_nbr(iface, &ns_hdr->tgt, false,
1908 NET_IPV6_NBR_STATE_INCOMPLETE);
1909 if (!nbr) {
1910 NET_DBG("Could not create new neighbor %s",
1911 log_strdup(net_sprint_ipv6_addr(&ns_hdr->tgt)));
1912 goto drop;
1913 }
1914
1915 if (pending) {
1916 if (!net_ipv6_nbr_data(nbr)->pending) {
1917 net_ipv6_nbr_data(nbr)->pending = net_pkt_ref(pending);
1918 } else {
1919 NET_DBG("Packet %p already pending for "
1920 "operation. Discarding pending %p and pkt %p",
1921 net_ipv6_nbr_data(nbr)->pending, pending, pkt);
1922 goto drop;
1923 }
1924
1925 NET_DBG("Setting timeout %d for NS", NS_REPLY_TIMEOUT);
1926
1927 net_ipv6_nbr_data(nbr)->send_ns = k_uptime_get();
1928
1929 /* Let's start the timer if necessary */
1930 if (!k_work_delayable_remaining_get(&ipv6_ns_reply_timer)) {
1931 k_work_reschedule(&ipv6_ns_reply_timer,
1932 K_MSEC(NS_REPLY_TIMEOUT));
1933 }
1934 }
1935
1936 dbg_addr_sent_tgt("Neighbor Solicitation", src, dst, &ns_hdr->tgt,
1937 pkt);
1938
1939 if (net_send_data(pkt) < 0) {
1940 NET_DBG("Cannot send NS %p (pending %p)", pkt, pending);
1941
1942 if (pending) {
1943 nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
1944 pending = NULL;
1945 }
1946
1947 goto drop;
1948 }
1949
1950 net_stats_update_ipv6_nd_sent(iface);
1951
1952 return 0;
1953
1954 drop:
1955 if (pending) {
1956 net_pkt_unref(pending);
1957 }
1958
1959 if (pkt) {
1960 net_pkt_unref(pkt);
1961 }
1962
1963 net_stats_update_ipv6_nd_drop(iface);
1964
1965 return ret;
1966 }
1967 #endif /* CONFIG_NET_IPV6_NBR_CACHE */
1968
1969 #if defined(CONFIG_NET_IPV6_ND)
net_ipv6_send_rs(struct net_if * iface)1970 int net_ipv6_send_rs(struct net_if *iface)
1971 {
1972 uint8_t llao_len = 0U;
1973 int ret = -ENOBUFS;
1974 const struct in6_addr *src;
1975 struct in6_addr dst;
1976 struct net_pkt *pkt;
1977
1978 net_ipv6_addr_create_ll_allrouters_mcast(&dst);
1979 src = net_if_ipv6_select_src_addr(iface, &dst);
1980
1981 if (!net_ipv6_is_addr_unspecified(src)) {
1982 llao_len = get_llao_len(iface);
1983 }
1984
1985 pkt = net_pkt_alloc_with_buffer(iface,
1986 sizeof(struct net_icmpv6_rs_hdr) +
1987 llao_len,
1988 AF_INET6, IPPROTO_ICMPV6,
1989 ND_NET_BUF_TIMEOUT);
1990 if (!pkt) {
1991 return -ENOMEM;
1992 }
1993
1994 net_pkt_set_ipv6_hop_limit(pkt, NET_IPV6_ND_HOP_LIMIT);
1995
1996 if (net_ipv6_create(pkt, src, &dst) ||
1997 net_icmpv6_create(pkt, NET_ICMPV6_RS, 0) ||
1998 net_pkt_memset(pkt, 0, sizeof(struct net_icmpv6_rs_hdr))) {
1999 goto drop;
2000 }
2001
2002 if (llao_len > 0) {
2003 if (!set_llao(pkt, net_if_get_link_addr(iface),
2004 llao_len, NET_ICMPV6_ND_OPT_SLLAO)) {
2005 goto drop;
2006 }
2007 }
2008
2009 net_pkt_cursor_init(pkt);
2010 net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
2011
2012 dbg_addr_sent("Router Solicitation", src, &dst, pkt);
2013
2014 if (net_send_data(pkt) < 0) {
2015 net_stats_update_ipv6_nd_drop(iface);
2016 ret = -EINVAL;
2017
2018 goto drop;
2019 }
2020
2021 net_stats_update_ipv6_nd_sent(iface);
2022
2023 return 0;
2024
2025 drop:
2026 net_pkt_unref(pkt);
2027
2028 return ret;
2029 }
2030
net_ipv6_start_rs(struct net_if * iface)2031 int net_ipv6_start_rs(struct net_if *iface)
2032 {
2033 return net_ipv6_send_rs(iface);
2034 }
2035
handle_ra_neighbor(struct net_pkt * pkt,uint8_t len)2036 static inline struct net_nbr *handle_ra_neighbor(struct net_pkt *pkt, uint8_t len)
2037 {
2038 struct net_linkaddr lladdr;
2039 struct net_linkaddr_storage llstorage;
2040
2041 if (!read_llao(pkt, len, &llstorage)) {
2042 return NULL;
2043 }
2044
2045 lladdr.len = llstorage.len;
2046 lladdr.addr = llstorage.addr;
2047
2048 return net_ipv6_nbr_add(net_pkt_iface(pkt),
2049 &NET_IPV6_HDR(pkt)->src,
2050 &lladdr, true,
2051 NET_IPV6_NBR_STATE_STALE);
2052 }
2053
handle_prefix_onlink(struct net_pkt * pkt,struct net_icmpv6_nd_opt_prefix_info * prefix_info)2054 static inline void handle_prefix_onlink(struct net_pkt *pkt,
2055 struct net_icmpv6_nd_opt_prefix_info *prefix_info)
2056 {
2057 struct net_if_ipv6_prefix *prefix;
2058
2059 prefix = net_if_ipv6_prefix_lookup(net_pkt_iface(pkt),
2060 &prefix_info->prefix,
2061 prefix_info->prefix_len);
2062 if (!prefix) {
2063 if (!prefix_info->valid_lifetime) {
2064 return;
2065 }
2066
2067 prefix = net_if_ipv6_prefix_add(net_pkt_iface(pkt),
2068 &prefix_info->prefix,
2069 prefix_info->prefix_len,
2070 prefix_info->valid_lifetime);
2071 if (prefix) {
2072 NET_DBG("Interface %p/%d add prefix %s/%d lifetime %u",
2073 net_pkt_iface(pkt),
2074 net_if_get_by_iface(net_pkt_iface(pkt)),
2075 log_strdup(net_sprint_ipv6_addr(
2076 &prefix_info->prefix)),
2077 prefix_info->prefix_len,
2078 prefix_info->valid_lifetime);
2079 } else {
2080 NET_ERR("Prefix %s/%d could not be added to "
2081 "iface %p/%d",
2082 log_strdup(net_sprint_ipv6_addr(
2083 &prefix_info->prefix)),
2084 prefix_info->prefix_len,
2085 net_pkt_iface(pkt),
2086 net_if_get_by_iface(net_pkt_iface(pkt)));
2087
2088 return;
2089 }
2090 }
2091
2092 switch (prefix_info->valid_lifetime) {
2093 case 0:
2094 NET_DBG("Interface %p/%d delete prefix %s/%d",
2095 net_pkt_iface(pkt),
2096 net_if_get_by_iface(net_pkt_iface(pkt)),
2097 log_strdup(net_sprint_ipv6_addr(&prefix_info->prefix)),
2098 prefix_info->prefix_len);
2099
2100 net_if_ipv6_prefix_rm(net_pkt_iface(pkt),
2101 &prefix->prefix,
2102 prefix->len);
2103 break;
2104
2105 case NET_IPV6_ND_INFINITE_LIFETIME:
2106 NET_DBG("Interface %p/%d prefix %s/%d infinite",
2107 net_pkt_iface(pkt),
2108 net_if_get_by_iface(net_pkt_iface(pkt)),
2109 log_strdup(net_sprint_ipv6_addr(&prefix->prefix)),
2110 prefix->len);
2111
2112 net_if_ipv6_prefix_set_lf(prefix, true);
2113 break;
2114
2115 default:
2116 NET_DBG("Interface %p/%d update prefix %s/%u lifetime %u",
2117 net_pkt_iface(pkt),
2118 net_if_get_by_iface(net_pkt_iface(pkt)),
2119 log_strdup(net_sprint_ipv6_addr(&prefix_info->prefix)),
2120 prefix_info->prefix_len, prefix_info->valid_lifetime);
2121
2122 net_if_ipv6_prefix_set_lf(prefix, false);
2123 net_if_ipv6_prefix_set_timer(prefix,
2124 prefix_info->valid_lifetime);
2125 break;
2126 }
2127 }
2128
2129 #define TWO_HOURS (2 * 60 * 60)
2130
remaining_lifetime(struct net_if_addr * ifaddr)2131 static inline uint32_t remaining_lifetime(struct net_if_addr *ifaddr)
2132 {
2133 return net_timeout_remaining(&ifaddr->lifetime, k_uptime_get_32());
2134 }
2135
handle_prefix_autonomous(struct net_pkt * pkt,struct net_icmpv6_nd_opt_prefix_info * prefix_info)2136 static inline void handle_prefix_autonomous(struct net_pkt *pkt,
2137 struct net_icmpv6_nd_opt_prefix_info *prefix_info)
2138 {
2139 struct in6_addr addr = { };
2140 struct net_if_addr *ifaddr;
2141
2142 /* Create IPv6 address using the given prefix and iid. We first
2143 * setup link local address, and then copy prefix over first 8
2144 * bytes of that address.
2145 */
2146 net_ipv6_addr_create_iid(&addr,
2147 net_if_get_link_addr(net_pkt_iface(pkt)));
2148 memcpy(&addr, &prefix_info->prefix, sizeof(struct in6_addr) / 2);
2149
2150 ifaddr = net_if_ipv6_addr_lookup(&addr, NULL);
2151 if (ifaddr && ifaddr->addr_type == NET_ADDR_AUTOCONF) {
2152 if (prefix_info->valid_lifetime ==
2153 NET_IPV6_ND_INFINITE_LIFETIME) {
2154 net_if_addr_set_lf(ifaddr, true);
2155 return;
2156 }
2157
2158 /* RFC 4862 ch 5.5.3 */
2159 if ((prefix_info->valid_lifetime > TWO_HOURS) ||
2160 (prefix_info->valid_lifetime >
2161 remaining_lifetime(ifaddr))) {
2162 NET_DBG("Timer updating for address %s "
2163 "long lifetime %u secs",
2164 log_strdup(net_sprint_ipv6_addr(&addr)),
2165 prefix_info->valid_lifetime);
2166
2167 net_if_ipv6_addr_update_lifetime(
2168 ifaddr, prefix_info->valid_lifetime);
2169 } else {
2170 NET_DBG("Timer updating for address %s "
2171 "lifetime %u secs",
2172 log_strdup(net_sprint_ipv6_addr(&addr)),
2173 TWO_HOURS);
2174
2175 net_if_ipv6_addr_update_lifetime(ifaddr, TWO_HOURS);
2176 }
2177
2178 net_if_addr_set_lf(ifaddr, false);
2179 } else {
2180 if (prefix_info->valid_lifetime ==
2181 NET_IPV6_ND_INFINITE_LIFETIME) {
2182 net_if_ipv6_addr_add(net_pkt_iface(pkt),
2183 &addr, NET_ADDR_AUTOCONF, 0);
2184 } else {
2185 net_if_ipv6_addr_add(net_pkt_iface(pkt),
2186 &addr, NET_ADDR_AUTOCONF,
2187 prefix_info->valid_lifetime);
2188 }
2189 }
2190 }
2191
handle_ra_prefix(struct net_pkt * pkt)2192 static inline bool handle_ra_prefix(struct net_pkt *pkt)
2193 {
2194 NET_PKT_DATA_ACCESS_DEFINE(rapfx_access,
2195 struct net_icmpv6_nd_opt_prefix_info);
2196 struct net_icmpv6_nd_opt_prefix_info *pfx_info;
2197 uint32_t valid_lifetime, preferred_lifetime;
2198
2199 pfx_info = (struct net_icmpv6_nd_opt_prefix_info *)
2200 net_pkt_get_data(pkt, &rapfx_access);
2201 if (!pfx_info) {
2202 return false;
2203 }
2204
2205 net_pkt_acknowledge_data(pkt, &rapfx_access);
2206
2207 valid_lifetime = ntohl(pfx_info->valid_lifetime);
2208 preferred_lifetime = ntohl(pfx_info->preferred_lifetime);
2209
2210 if (valid_lifetime >= preferred_lifetime &&
2211 !net_ipv6_is_ll_addr(&pfx_info->prefix)) {
2212 if (pfx_info->flags & NET_ICMPV6_RA_FLAG_ONLINK) {
2213 handle_prefix_onlink(pkt, pfx_info);
2214 }
2215
2216 if ((pfx_info->flags & NET_ICMPV6_RA_FLAG_AUTONOMOUS) &&
2217 valid_lifetime &&
2218 (pfx_info->prefix_len == NET_IPV6_DEFAULT_PREFIX_LEN)) {
2219 handle_prefix_autonomous(pkt, pfx_info);
2220 }
2221 }
2222
2223 return true;
2224 }
2225
2226 #if defined(CONFIG_NET_6LO_CONTEXT)
2227 /* 6lowpan Context Option RFC 6775, 4.2 */
handle_ra_6co(struct net_pkt * pkt,uint8_t len)2228 static inline bool handle_ra_6co(struct net_pkt *pkt, uint8_t len)
2229 {
2230 NET_PKT_DATA_ACCESS_DEFINE(ctx_access, struct net_icmpv6_nd_opt_6co);
2231 struct net_icmpv6_nd_opt_6co *context;
2232
2233 context = (struct net_icmpv6_nd_opt_6co *)
2234 net_pkt_get_data(pkt, &ctx_access);
2235 if (!context) {
2236 return false;
2237 }
2238
2239 /* RFC 6775, 4.2
2240 * Context Length: 8-bit unsigned integer. The number of leading
2241 * bits in the Context Prefix field that are valid. The value ranges
2242 * from 0 to 128. If it is more than 64, then the Length MUST be 3.
2243 */
2244 if ((context->context_len > 64 && len != 3U) ||
2245 (context->context_len <= 64U && len != 2U)) {
2246 return false;
2247 }
2248
2249 context->context_len = context->context_len / 8U;
2250
2251 /* context_len: The number of leading bits in the Context Prefix
2252 * field that are valid. Rest must be set to 0 by the sender and
2253 * ignored by the receiver. But since there is no way to make sure
2254 * the sender followed the rule, let's make sure rest is set to 0.
2255 */
2256 if (context->context_len != sizeof(struct in6_addr)) {
2257 (void)memset(context->prefix.s6_addr + context->context_len, 0,
2258 sizeof(struct in6_addr) - context->context_len);
2259 }
2260
2261 net_6lo_set_context(net_pkt_iface(pkt), context);
2262
2263 return true;
2264 }
2265 #endif
2266
handle_ra_input(struct net_pkt * pkt,struct net_ipv6_hdr * ip_hdr,struct net_icmp_hdr * icmp_hdr)2267 static enum net_verdict handle_ra_input(struct net_pkt *pkt,
2268 struct net_ipv6_hdr *ip_hdr,
2269 struct net_icmp_hdr *icmp_hdr)
2270 {
2271 NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ra_access,
2272 struct net_icmpv6_ra_hdr);
2273 NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr);
2274 uint16_t length = net_pkt_get_len(pkt);
2275 struct net_nbr *nbr = NULL;
2276 struct net_icmpv6_nd_opt_hdr *nd_opt_hdr;
2277 struct net_icmpv6_ra_hdr *ra_hdr;
2278 struct net_if_router *router;
2279 uint32_t mtu, reachable_time, retrans_timer;
2280 uint16_t router_lifetime;
2281
2282 ra_hdr = (struct net_icmpv6_ra_hdr *)net_pkt_get_data(pkt, &ra_access);
2283 if (!ra_hdr) {
2284 NET_ERR("DROP: NULL RA header");
2285 goto drop;
2286 }
2287
2288 dbg_addr_recv("Router Advertisement", &ip_hdr->src, &ip_hdr->dst, pkt);
2289
2290 net_stats_update_ipv6_nd_recv(net_pkt_iface(pkt));
2291
2292 if (((length < (sizeof(struct net_ipv6_hdr) +
2293 sizeof(struct net_icmp_hdr) +
2294 sizeof(struct net_icmpv6_ra_hdr) +
2295 sizeof(struct net_icmpv6_nd_opt_hdr))) ||
2296 (ip_hdr->hop_limit != NET_IPV6_ND_HOP_LIMIT) ||
2297 !net_ipv6_is_ll_addr(&ip_hdr->src)) &&
2298 icmp_hdr->code != 0U) {
2299 goto drop;
2300 }
2301
2302 net_pkt_acknowledge_data(pkt, &ra_access);
2303
2304 router_lifetime = ntohs(ra_hdr->router_lifetime);
2305 reachable_time = ntohl(ra_hdr->reachable_time);
2306 retrans_timer = ntohl(ra_hdr->retrans_timer);
2307
2308 if (ra_hdr->cur_hop_limit) {
2309 net_ipv6_set_hop_limit(net_pkt_iface(pkt),
2310 ra_hdr->cur_hop_limit);
2311 NET_DBG("New hop limit %d",
2312 net_if_ipv6_get_hop_limit(net_pkt_iface(pkt)));
2313 }
2314
2315 if (reachable_time && reachable_time <= MAX_REACHABLE_TIME &&
2316 (net_if_ipv6_get_reachable_time(net_pkt_iface(pkt)) !=
2317 reachable_time)) {
2318 net_if_ipv6_set_base_reachable_time(net_pkt_iface(pkt),
2319 reachable_time);
2320 net_if_ipv6_set_reachable_time(
2321 net_pkt_iface(pkt)->config.ip.ipv6);
2322 }
2323
2324 if (retrans_timer) {
2325 net_if_ipv6_set_retrans_timer(net_pkt_iface(pkt),
2326 ra_hdr->retrans_timer);
2327 }
2328
2329 net_pkt_set_ipv6_ext_opt_len(pkt, sizeof(struct net_icmpv6_ra_hdr));
2330 length -= (sizeof(struct net_ipv6_hdr) + sizeof(struct net_icmp_hdr));
2331
2332 nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
2333 net_pkt_get_data(pkt, &nd_access);
2334 while (nd_opt_hdr) {
2335 net_pkt_acknowledge_data(pkt, &nd_access);
2336
2337 switch (nd_opt_hdr->type) {
2338 case NET_ICMPV6_ND_OPT_SLLAO:
2339 nbr = handle_ra_neighbor(pkt, nd_opt_hdr->len);
2340 if (!nbr) {
2341 goto drop;
2342 }
2343
2344 break;
2345 case NET_ICMPV6_ND_OPT_MTU:
2346 /* MTU has reserved 2 bytes, so skip it. */
2347 if (net_pkt_skip(pkt, 2) ||
2348 net_pkt_read_be32(pkt, &mtu)) {
2349 goto drop;
2350 }
2351
2352 if (mtu < MIN_IPV6_MTU || mtu > MAX_IPV6_MTU) {
2353 NET_ERR("DROP: Unsupported MTU %u, min is %u, "
2354 "max is %u",
2355 mtu, MIN_IPV6_MTU, MAX_IPV6_MTU);
2356 goto drop;
2357 }
2358
2359 net_if_set_mtu(net_pkt_iface(pkt), mtu);
2360
2361 break;
2362 case NET_ICMPV6_ND_OPT_PREFIX_INFO:
2363 if (nd_opt_hdr->len != 4) {
2364 NET_ERR("DROP: Invalid %s length (%d)",
2365 "prefix opt", nd_opt_hdr->len);
2366 goto drop;
2367 }
2368
2369 if (!handle_ra_prefix(pkt)) {
2370 goto drop;
2371 }
2372
2373 break;
2374 #if defined(CONFIG_NET_6LO_CONTEXT)
2375 case NET_ICMPV6_ND_OPT_6CO:
2376 /* RFC 6775, 4.2 (Length)*/
2377 if (!(nd_opt_hdr->len == 2U || nd_opt_hdr->len == 3U)) {
2378 NET_ERR("DROP: Invalid %s length %d",
2379 "6CO", nd_opt_hdr->len);
2380 goto drop;
2381 }
2382
2383 if (!handle_ra_6co(pkt, nd_opt_hdr->len)) {
2384 goto drop;
2385 }
2386
2387 break;
2388 #endif
2389 case NET_ICMPV6_ND_OPT_ROUTE:
2390 NET_DBG("Route option skipped");
2391 goto skip;
2392
2393 #if defined(CONFIG_NET_IPV6_RA_RDNSS)
2394 case NET_ICMPV6_ND_OPT_RDNSS:
2395 NET_DBG("RDNSS option skipped");
2396 goto skip;
2397 #endif
2398
2399 case NET_ICMPV6_ND_OPT_DNSSL:
2400 NET_DBG("DNSSL option skipped");
2401 goto skip;
2402
2403 default:
2404 NET_DBG("Unknown ND option 0x%x", nd_opt_hdr->type);
2405 skip:
2406 if (net_pkt_skip(pkt, nd_opt_hdr->len * 8U - 2)) {
2407 goto drop;
2408 }
2409
2410 break;
2411 }
2412
2413 nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
2414 net_pkt_get_data(pkt, &nd_access);
2415 }
2416
2417 router = net_if_ipv6_router_lookup(net_pkt_iface(pkt), &ip_hdr->src);
2418 if (router) {
2419 if (!router_lifetime) {
2420 /* TODO: Start rs_timer on iface if no routers
2421 * at all available on iface.
2422 */
2423 net_if_ipv6_router_rm(router);
2424 } else {
2425 if (nbr) {
2426 net_ipv6_nbr_data(nbr)->is_router = true;
2427 }
2428
2429 net_if_ipv6_router_update_lifetime(
2430 router, router_lifetime);
2431 }
2432 } else {
2433 net_if_ipv6_router_add(net_pkt_iface(pkt),
2434 &ip_hdr->src, router_lifetime);
2435 }
2436
2437 if (nbr && net_ipv6_nbr_data(nbr)->pending) {
2438 NET_DBG("Sending pending pkt %p to %s",
2439 net_ipv6_nbr_data(nbr)->pending,
2440 log_strdup(net_sprint_ipv6_addr(&NET_IPV6_HDR(
2441 net_ipv6_nbr_data(nbr)->pending)->dst)));
2442
2443 if (net_send_data(net_ipv6_nbr_data(nbr)->pending) < 0) {
2444 net_pkt_unref(net_ipv6_nbr_data(nbr)->pending);
2445 }
2446
2447 nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
2448 }
2449
2450 /* Cancel the RS timer on iface */
2451 net_if_stop_rs(net_pkt_iface(pkt));
2452
2453 net_pkt_unref(pkt);
2454
2455 return NET_OK;
2456
2457 drop:
2458 net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt));
2459
2460 return NET_DROP;
2461 }
2462 #endif /* CONFIG_NET_IPV6_ND */
2463
2464 #if defined(CONFIG_NET_IPV6_NBR_CACHE)
2465 static struct net_icmpv6_handler ns_input_handler = {
2466 .type = NET_ICMPV6_NS,
2467 .code = 0,
2468 .handler = handle_ns_input,
2469 };
2470
2471 static struct net_icmpv6_handler na_input_handler = {
2472 .type = NET_ICMPV6_NA,
2473 .code = 0,
2474 .handler = handle_na_input,
2475 };
2476 #endif /* CONFIG_NET_IPV6_NBR_CACHE */
2477
2478 #if defined(CONFIG_NET_IPV6_ND)
2479 static struct net_icmpv6_handler ra_input_handler = {
2480 .type = NET_ICMPV6_RA,
2481 .code = 0,
2482 .handler = handle_ra_input,
2483 };
2484 #endif /* CONFIG_NET_IPV6_ND */
2485
net_ipv6_nbr_init(void)2486 void net_ipv6_nbr_init(void)
2487 {
2488 #if defined(CONFIG_NET_IPV6_NBR_CACHE)
2489 net_icmpv6_register_handler(&ns_input_handler);
2490 net_icmpv6_register_handler(&na_input_handler);
2491 k_work_init_delayable(&ipv6_ns_reply_timer, ipv6_ns_reply_timeout);
2492 k_sem_init(&nbr_lock, 1, K_SEM_MAX_LIMIT);
2493 #endif
2494 #if defined(CONFIG_NET_IPV6_ND)
2495 net_icmpv6_register_handler(&ra_input_handler);
2496 k_work_init_delayable(&ipv6_nd_reachable_timer,
2497 ipv6_nd_reachable_timeout);
2498 #endif
2499 }
2500