]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
IPv6 RA: Support the Retrans Timer field (IPv6 Conformance Test: v6LC.2.1.5)
[thirdparty/systemd.git] / src / network / networkd-ndisc.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2014 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <arpa/inet.h>
7 #include <netinet/icmp6.h>
8 #include <linux/if.h>
9 #include <linux/if_arp.h>
10
11 #include "sd-ndisc.h"
12
13 #include "event-util.h"
14 #include "missing_network.h"
15 #include "networkd-address-generation.h"
16 #include "networkd-address.h"
17 #include "networkd-dhcp6.h"
18 #include "networkd-manager.h"
19 #include "networkd-ndisc.h"
20 #include "networkd-queue.h"
21 #include "networkd-route.h"
22 #include "networkd-state-file.h"
23 #include "string-table.h"
24 #include "string-util.h"
25 #include "strv.h"
26 #include "sysctl-util.h"
27
28 #define NDISC_DNSSL_MAX 64U
29 #define NDISC_RDNSS_MAX 64U
30 /* Not defined in the RFC, but let's set an upper limit to make not consume much memory.
31 * This should be safe as typically there should be at most 1 portal per network. */
32 #define NDISC_CAPTIVE_PORTAL_MAX 64U
33 /* Neither defined in the RFC. Just for safety. Otherwise, malformed messages can make clients trigger OOM.
34 * Not sure if the threshold is high enough. Let's adjust later if not. */
35 #define NDISC_PREF64_MAX 64U
36
37 bool link_ipv6_accept_ra_enabled(Link *link) {
38 assert(link);
39
40 if (!socket_ipv6_is_supported())
41 return false;
42
43 if (link->flags & IFF_LOOPBACK)
44 return false;
45
46 if (link->iftype == ARPHRD_CAN)
47 return false;
48
49 if (!link->network)
50 return false;
51
52 if (!link_may_have_ipv6ll(link, /* check_multicast = */ true))
53 return false;
54
55 assert(link->network->ipv6_accept_ra >= 0);
56 return link->network->ipv6_accept_ra;
57 }
58
59 void network_adjust_ipv6_accept_ra(Network *network) {
60 assert(network);
61
62 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
63 if (network->ipv6_accept_ra > 0)
64 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link-local addressing is disabled or not supported. "
65 "Disabling IPv6AcceptRA=.", network->filename);
66 network->ipv6_accept_ra = false;
67 }
68
69 if (network->ipv6_accept_ra < 0)
70 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
71 network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6);
72
73 /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
74 * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
75 if (!set_isempty(network->ndisc_allow_listed_router))
76 network->ndisc_deny_listed_router = set_free_free(network->ndisc_deny_listed_router);
77 if (!set_isempty(network->ndisc_allow_listed_prefix))
78 network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix);
79 if (!set_isempty(network->ndisc_allow_listed_route_prefix))
80 network->ndisc_deny_listed_route_prefix = set_free_free(network->ndisc_deny_listed_route_prefix);
81 }
82
83 static int ndisc_check_ready(Link *link);
84
85 static int ndisc_address_ready_callback(Address *address) {
86 Address *a;
87
88 assert(address);
89 assert(address->link);
90
91 SET_FOREACH(a, address->link->addresses)
92 if (a->source == NETWORK_CONFIG_SOURCE_NDISC)
93 a->callback = NULL;
94
95 return ndisc_check_ready(address->link);
96 }
97
98 static int ndisc_check_ready(Link *link) {
99 bool found = false, ready = false;
100 Address *address;
101
102 assert(link);
103
104 if (link->ndisc_messages > 0) {
105 log_link_debug(link, "%s(): SLAAC addresses and routes are not set.", __func__);
106 return 0;
107 }
108
109 SET_FOREACH(address, link->addresses) {
110 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
111 continue;
112
113 found = true;
114
115 if (address_is_ready(address)) {
116 ready = true;
117 break;
118 }
119 }
120
121 if (found && !ready) {
122 SET_FOREACH(address, link->addresses)
123 if (address->source == NETWORK_CONFIG_SOURCE_NDISC)
124 address->callback = ndisc_address_ready_callback;
125
126 log_link_debug(link, "%s(): no SLAAC address is ready.", __func__);
127 return 0;
128 }
129
130 link->ndisc_configured = true;
131 log_link_debug(link, "SLAAC addresses and routes set.");
132
133 link_check_ready(link);
134 return 0;
135 }
136
137 static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
138 int r;
139
140 assert(link);
141
142 r = route_configure_handler_internal(rtnl, m, link, route, "Could not set NDisc route");
143 if (r <= 0)
144 return r;
145
146 r = ndisc_check_ready(link);
147 if (r < 0)
148 link_enter_failed(link);
149
150 return 1;
151 }
152
153 static void ndisc_set_route_priority(Link *link, Route *route) {
154 assert(link);
155 assert(route);
156
157 if (route->priority_set)
158 return; /* explicitly configured. */
159
160 switch (route->pref) {
161 case SD_NDISC_PREFERENCE_LOW:
162 route->priority = link->network->ipv6_accept_ra_route_metric_low;
163 break;
164 case SD_NDISC_PREFERENCE_MEDIUM:
165 route->priority = link->network->ipv6_accept_ra_route_metric_medium;
166 break;
167 case SD_NDISC_PREFERENCE_HIGH:
168 route->priority = link->network->ipv6_accept_ra_route_metric_high;
169 break;
170 default:
171 assert_not_reached();
172 }
173 }
174
175 static int ndisc_request_route(Route *route, Link *link, sd_ndisc_router *rt) {
176 struct in6_addr router;
177 uint8_t hop_limit = 0;
178 uint32_t mtu = 0;
179 bool is_new;
180 int r;
181
182 assert(route);
183 assert(link);
184 assert(link->network);
185 assert(rt);
186
187 r = sd_ndisc_router_get_address(rt, &router);
188 if (r < 0)
189 return r;
190
191 if (link->network->ipv6_accept_ra_use_mtu) {
192 r = sd_ndisc_router_get_mtu(rt, &mtu);
193 if (r < 0 && r != -ENODATA)
194 return log_link_warning_errno(link, r, "Failed to get default router MTU from RA: %m");
195 }
196
197 if (link->network->ipv6_accept_ra_use_hop_limit) {
198 r = sd_ndisc_router_get_hop_limit(rt, &hop_limit);
199 if (r < 0 && r != -ENODATA)
200 return log_link_warning_errno(link, r, "Failed to get default router hop limit from RA: %m");
201 }
202
203 route->source = NETWORK_CONFIG_SOURCE_NDISC;
204 route->provider.in6 = router;
205 if (!route->table_set)
206 route->table = link_get_ipv6_accept_ra_route_table(link);
207 ndisc_set_route_priority(link, route);
208 if (!route->protocol_set)
209 route->protocol = RTPROT_RA;
210 r = route_metric_set(&route->metric, RTAX_MTU, mtu);
211 if (r < 0)
212 return r;
213 r = route_metric_set(&route->metric, RTAX_HOPLIMIT, hop_limit);
214 if (r < 0)
215 return r;
216 r = route_metric_set(&route->metric, RTAX_QUICKACK, link->network->ipv6_accept_ra_quickack);
217 if (r < 0)
218 return r;
219
220 r = route_adjust_nexthops(route, link);
221 if (r < 0)
222 return r;
223
224 is_new = route_get(NULL, link, route, NULL) < 0;
225
226 r = link_request_route(link, route, &link->ndisc_messages, ndisc_route_handler);
227 if (r < 0)
228 return r;
229 if (r > 0 && is_new)
230 link->ndisc_configured = false;
231
232 return 0;
233 }
234
235 static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
236 int r;
237
238 assert(link);
239
240 r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address");
241 if (r <= 0)
242 return r;
243
244 r = ndisc_check_ready(link);
245 if (r < 0)
246 link_enter_failed(link);
247
248 return 1;
249 }
250
251 static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {
252 _cleanup_(address_unrefp) Address *address = in;
253 struct in6_addr router;
254 bool is_new;
255 int r;
256
257 assert(address);
258 assert(link);
259 assert(rt);
260
261 r = sd_ndisc_router_get_address(rt, &router);
262 if (r < 0)
263 return r;
264
265 address->source = NETWORK_CONFIG_SOURCE_NDISC;
266 address->provider.in6 = router;
267
268 r = free_and_strdup_warn(&address->netlabel, link->network->ndisc_netlabel);
269 if (r < 0)
270 return r;
271
272 is_new = address_get(link, address, NULL) < 0;
273
274 r = link_request_address(link, address, &link->ndisc_messages,
275 ndisc_address_handler, NULL);
276 if (r < 0)
277 return r;
278 if (r > 0 && is_new)
279 link->ndisc_configured = false;
280
281 return 0;
282 }
283
284 static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
285 usec_t lifetime_usec;
286 struct in6_addr gateway;
287 unsigned preference;
288 int r;
289
290 assert(link);
291 assert(link->network);
292 assert(rt);
293
294 if (!link->network->ipv6_accept_ra_use_gateway &&
295 hashmap_isempty(link->network->routes_by_section))
296 return 0;
297
298 r = sd_ndisc_router_get_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
299 if (r < 0)
300 return log_link_warning_errno(link, r, "Failed to get gateway lifetime from RA: %m");
301
302 r = sd_ndisc_router_get_address(rt, &gateway);
303 if (r < 0)
304 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
305
306 if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
307 if (DEBUG_LOGGING)
308 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
309 IN6_ADDR_TO_STRING(&gateway));
310 return 0;
311 }
312
313 r = sd_ndisc_router_get_preference(rt, &preference);
314 if (r < 0)
315 return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
316
317 if (link->network->ipv6_accept_ra_use_gateway) {
318 _cleanup_(route_freep) Route *route = NULL;
319
320 r = route_new(&route);
321 if (r < 0)
322 return log_oom();
323
324 route->family = AF_INET6;
325 route->pref = preference;
326 route->nexthop.family = AF_INET6;
327 route->nexthop.gw.in6 = gateway;
328 route->lifetime_usec = lifetime_usec;
329
330 r = ndisc_request_route(route, link, rt);
331 if (r < 0)
332 return log_link_warning_errno(link, r, "Could not request default route: %m");
333 }
334
335 Route *route_gw;
336 HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
337 _cleanup_(route_freep) Route *route = NULL;
338
339 if (!route_gw->gateway_from_dhcp_or_ra)
340 continue;
341
342 if (route_gw->nexthop.family != AF_INET6)
343 continue;
344
345 r = route_dup(route_gw, NULL, &route);
346 if (r < 0)
347 return r;
348
349 route->nexthop.gw.in6 = gateway;
350 if (!route->pref_set)
351 route->pref = preference;
352 route->lifetime_usec = lifetime_usec;
353
354 r = ndisc_request_route(route, link, rt);
355 if (r < 0)
356 return log_link_warning_errno(link, r, "Could not request gateway: %m");
357 }
358
359 return 0;
360 }
361
362 static int ndisc_router_process_icmp6_ratelimit(Link *link, sd_ndisc_router *rt) {
363 usec_t icmp6_ratelimit, msec;
364 int r;
365
366 assert(link);
367 assert(link->network);
368 assert(rt);
369
370 if (!link->network->ipv6_accept_ra_use_icmp6_ratelimit)
371 return 0;
372
373 r = sd_ndisc_router_get_icmp6_ratelimit(rt, &icmp6_ratelimit);
374 if (r < 0) {
375 log_link_debug(link, "Failed to get ICMP6 ratelimit from RA, ignoring: %m");
376 return 0;
377 }
378
379 /* We do not allow 0 here. */
380 if (!timestamp_is_set(icmp6_ratelimit))
381 return 0;
382
383 msec = DIV_ROUND_UP(icmp6_ratelimit, USEC_PER_MSEC);
384 if (msec <= 0 || msec > INT_MAX)
385 return 0;
386
387 /* Limit the maximal rates for sending ICMPv6 packets. 0 to disable any limiting, otherwise the
388 * minimal space between responses in milliseconds. Default: 1000. */
389 r = sysctl_write_ip_property_int(AF_INET6, NULL, "icmp/ratelimit", (int) msec);
390 if (r < 0)
391 log_link_warning_errno(link, r, "Failed to apply ICMP6 ratelimit, ignoring: %m");
392
393 return 0;
394 }
395
396 static int ndisc_router_process_retransmission_time(Link *link, sd_ndisc_router *rt) {
397 usec_t retrans_time, msec;
398 int r;
399
400 assert(link);
401 assert(link->network);
402 assert(rt);
403
404 if (!link->network->ipv6_accept_ra_use_retransmission_time)
405 return 0;
406
407 r = sd_ndisc_router_get_retransmission_time(rt, &retrans_time);
408 if (r < 0) {
409 log_link_debug_errno(link, r, "Failed to get retransmission time from RA, ignoring: %m");
410 return 0;
411 }
412
413 /* 0 is the unspecified value and must not be set (see RFC4861, 6.3.4) */
414 if (!timestamp_is_set(retrans_time))
415 return 0;
416
417 msec = DIV_ROUND_UP(retrans_time, USEC_PER_MSEC);
418 if (msec <= 0 || msec > UINT32_MAX) {
419 log_link_debug(link, "Failed to get retransmission time from RA - out of range (%"PRIu64"), ignoring", msec);
420 return 0;
421 }
422
423 /* Set the retransmission time for Neigbor Solicitations. */
424 r = sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "retrans_time_ms", (uint32_t) msec);
425 if (r < 0)
426 log_link_warning_errno(
427 link, r, "Failed to apply neighbor retransmission time (%"PRIu64"), ignoring: %m", msec);
428
429 return 0;
430 }
431
432 static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
433 usec_t lifetime_valid_usec, lifetime_preferred_usec;
434 _cleanup_set_free_ Set *addresses = NULL;
435 struct in6_addr prefix, *a;
436 unsigned prefixlen;
437 int r;
438
439 assert(link);
440 assert(link->network);
441 assert(rt);
442
443 if (!link->network->ipv6_accept_ra_use_autonomous_prefix)
444 return 0;
445
446 r = sd_ndisc_router_prefix_get_address(rt, &prefix);
447 if (r < 0)
448 return log_link_warning_errno(link, r, "Failed to get prefix address: %m");
449
450 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
451 if (r < 0)
452 return log_link_warning_errno(link, r, "Failed to get prefix length: %m");
453
454 /* ndisc_generate_addresses() below requires the prefix length <= 64. */
455 if (prefixlen > 64) {
456 log_link_debug(link, "Prefix is longer than 64, ignoring autonomous prefix %s.",
457 IN6_ADDR_PREFIX_TO_STRING(&prefix, prefixlen));
458 return 0;
459 }
460
461 r = sd_ndisc_router_prefix_get_valid_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_valid_usec);
462 if (r < 0)
463 return log_link_warning_errno(link, r, "Failed to get prefix valid lifetime: %m");
464
465 r = sd_ndisc_router_prefix_get_preferred_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_preferred_usec);
466 if (r < 0)
467 return log_link_warning_errno(link, r, "Failed to get prefix preferred lifetime: %m");
468
469 /* The preferred lifetime is never greater than the valid lifetime */
470 if (lifetime_preferred_usec > lifetime_valid_usec)
471 return 0;
472
473 r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses);
474 if (r < 0)
475 return log_link_warning_errno(link, r, "Failed to generate SLAAC addresses: %m");
476
477 SET_FOREACH(a, addresses) {
478 _cleanup_(address_unrefp) Address *address = NULL;
479
480 r = address_new(&address);
481 if (r < 0)
482 return log_oom();
483
484 address->family = AF_INET6;
485 address->in_addr.in6 = *a;
486 address->prefixlen = prefixlen;
487 address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
488 address->lifetime_valid_usec = lifetime_valid_usec;
489 address->lifetime_preferred_usec = lifetime_preferred_usec;
490
491 r = ndisc_request_address(TAKE_PTR(address), link, rt);
492 if (r < 0)
493 return log_link_warning_errno(link, r, "Could not request SLAAC address: %m");
494 }
495
496 return 0;
497 }
498
499 static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
500 _cleanup_(route_freep) Route *route = NULL;
501 unsigned prefixlen, preference;
502 usec_t lifetime_usec;
503 struct in6_addr prefix;
504 int r;
505
506 assert(link);
507 assert(link->network);
508 assert(rt);
509
510 if (!link->network->ipv6_accept_ra_use_onlink_prefix)
511 return 0;
512
513 r = sd_ndisc_router_prefix_get_valid_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
514 if (r < 0)
515 return log_link_warning_errno(link, r, "Failed to get prefix lifetime: %m");
516
517 r = sd_ndisc_router_prefix_get_address(rt, &prefix);
518 if (r < 0)
519 return log_link_warning_errno(link, r, "Failed to get prefix address: %m");
520
521 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
522 if (r < 0)
523 return log_link_warning_errno(link, r, "Failed to get prefix length: %m");
524
525 /* Prefix Information option does not have preference, hence we use the 'main' preference here */
526 r = sd_ndisc_router_get_preference(rt, &preference);
527 if (r < 0)
528 log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
529
530 r = route_new(&route);
531 if (r < 0)
532 return log_oom();
533
534 route->family = AF_INET6;
535 route->dst.in6 = prefix;
536 route->dst_prefixlen = prefixlen;
537 route->pref = preference;
538 route->lifetime_usec = lifetime_usec;
539
540 r = ndisc_request_route(route, link, rt);
541 if (r < 0)
542 return log_link_warning_errno(link, r, "Could not request prefix route: %m");
543
544 return 0;
545 }
546
547 static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) {
548 unsigned prefixlen;
549 struct in6_addr a;
550 uint8_t flags;
551 int r;
552
553 assert(link);
554 assert(link->network);
555 assert(rt);
556
557 r = sd_ndisc_router_prefix_get_address(rt, &a);
558 if (r < 0)
559 return log_link_warning_errno(link, r, "Failed to get prefix address: %m");
560
561 /* RFC 4861 Section 4.6.2:
562 * A router SHOULD NOT send a prefix option for the link-local prefix and a host SHOULD ignore such
563 * a prefix option. */
564 if (in6_addr_is_link_local(&a)) {
565 log_link_debug(link, "Received link-local prefix, ignoring autonomous prefix.");
566 return 0;
567 }
568
569 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
570 if (r < 0)
571 return log_link_warning_errno(link, r, "Failed to get prefix length: %m");
572
573 if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) {
574 if (DEBUG_LOGGING)
575 log_link_debug(link, "Prefix '%s' is %s, ignoring",
576 !set_isempty(link->network->ndisc_allow_listed_prefix) ? "not in allow list"
577 : "in deny list",
578 IN6_ADDR_PREFIX_TO_STRING(&a, prefixlen));
579 return 0;
580 }
581
582 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
583 if (r < 0)
584 return log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m");
585
586 if (FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) {
587 r = ndisc_router_process_onlink_prefix(link, rt);
588 if (r < 0)
589 return r;
590 }
591
592 if (FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) {
593 r = ndisc_router_process_autonomous_prefix(link, rt);
594 if (r < 0)
595 return r;
596 }
597
598 return 0;
599 }
600
601 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
602 _cleanup_(route_freep) Route *route = NULL;
603 unsigned preference, prefixlen;
604 struct in6_addr gateway, dst;
605 usec_t lifetime_usec;
606 int r;
607
608 assert(link);
609
610 if (!link->network->ipv6_accept_ra_use_route_prefix)
611 return 0;
612
613 r = sd_ndisc_router_route_get_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
614 if (r < 0)
615 return log_link_warning_errno(link, r, "Failed to get route lifetime from RA: %m");
616
617 r = sd_ndisc_router_route_get_address(rt, &dst);
618 if (r < 0)
619 return log_link_warning_errno(link, r, "Failed to get route destination address: %m");
620
621 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
622 if (r < 0)
623 return log_link_warning_errno(link, r, "Failed to get route prefix length: %m");
624
625 if (in6_addr_is_null(&dst) && prefixlen == 0) {
626 log_link_debug(link, "Route prefix is ::/0, ignoring");
627 return 0;
628 }
629
630 if (in6_prefix_is_filtered(&dst, prefixlen,
631 link->network->ndisc_allow_listed_route_prefix,
632 link->network->ndisc_deny_listed_route_prefix)) {
633
634 if (DEBUG_LOGGING)
635 log_link_debug(link, "Route prefix %s is %s, ignoring",
636 !set_isempty(link->network->ndisc_allow_listed_route_prefix) ? "not in allow list"
637 : "in deny list",
638 IN6_ADDR_PREFIX_TO_STRING(&dst, prefixlen));
639 return 0;
640 }
641
642 r = sd_ndisc_router_get_address(rt, &gateway);
643 if (r < 0)
644 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
645
646 if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
647 if (DEBUG_LOGGING)
648 log_link_debug(link, "Advertised route gateway %s is local to the link, ignoring route",
649 IN6_ADDR_TO_STRING(&gateway));
650 return 0;
651 }
652
653 r = sd_ndisc_router_route_get_preference(rt, &preference);
654 if (r == -EOPNOTSUPP) {
655 log_link_debug_errno(link, r, "Received route prefix with unsupported preference, ignoring: %m");
656 return 0;
657 }
658 if (r < 0)
659 return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
660
661 r = route_new(&route);
662 if (r < 0)
663 return log_oom();
664
665 route->family = AF_INET6;
666 route->pref = preference;
667 route->nexthop.gw.in6 = gateway;
668 route->nexthop.family = AF_INET6;
669 route->dst.in6 = dst;
670 route->dst_prefixlen = prefixlen;
671 route->lifetime_usec = lifetime_usec;
672
673 r = ndisc_request_route(route, link, rt);
674 if (r < 0)
675 return log_link_warning_errno(link, r, "Could not request additional route: %m");
676
677 return 0;
678 }
679
680 static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
681 siphash24_compress_typesafe(x->address, state);
682 }
683
684 static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
685 return memcmp(&a->address, &b->address, sizeof(a->address));
686 }
687
688 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
689 ndisc_rdnss_hash_ops,
690 NDiscRDNSS,
691 ndisc_rdnss_hash_func,
692 ndisc_rdnss_compare_func,
693 free);
694
695 static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
696 usec_t lifetime_usec;
697 const struct in6_addr *a;
698 struct in6_addr router;
699 bool updated = false, logged_about_too_many = false;
700 int n, r;
701
702 assert(link);
703 assert(link->network);
704 assert(rt);
705
706 if (!link->network->ipv6_accept_ra_use_dns)
707 return 0;
708
709 r = sd_ndisc_router_get_address(rt, &router);
710 if (r < 0)
711 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
712
713 r = sd_ndisc_router_rdnss_get_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
714 if (r < 0)
715 return log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
716
717 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
718 if (n < 0)
719 return log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m");
720
721 for (int j = 0; j < n; j++) {
722 _cleanup_free_ NDiscRDNSS *x = NULL;
723 NDiscRDNSS *rdnss, d = {
724 .address = a[j],
725 };
726
727 if (lifetime_usec == 0) {
728 /* The entry is outdated. */
729 free(set_remove(link->ndisc_rdnss, &d));
730 updated = true;
731 continue;
732 }
733
734 rdnss = set_get(link->ndisc_rdnss, &d);
735 if (rdnss) {
736 rdnss->router = router;
737 rdnss->lifetime_usec = lifetime_usec;
738 continue;
739 }
740
741 if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX) {
742 if (!logged_about_too_many)
743 log_link_warning(link, "Too many RDNSS records per link. Only first %u records will be used.", NDISC_RDNSS_MAX);
744 logged_about_too_many = true;
745 continue;
746 }
747
748 x = new(NDiscRDNSS, 1);
749 if (!x)
750 return log_oom();
751
752 *x = (NDiscRDNSS) {
753 .address = a[j],
754 .router = router,
755 .lifetime_usec = lifetime_usec,
756 };
757
758 r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
759 if (r < 0)
760 return log_oom();
761 assert(r > 0);
762
763 updated = true;
764 }
765
766 if (updated)
767 link_dirty(link);
768
769 return 0;
770 }
771
772 static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
773 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x), state);
774 }
775
776 static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
777 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
778 }
779
780 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
781 ndisc_dnssl_hash_ops,
782 NDiscDNSSL,
783 ndisc_dnssl_hash_func,
784 ndisc_dnssl_compare_func,
785 free);
786
787 static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
788 _cleanup_strv_free_ char **l = NULL;
789 usec_t lifetime_usec;
790 struct in6_addr router;
791 bool updated = false, logged_about_too_many = false;
792 int r;
793
794 assert(link);
795 assert(link->network);
796 assert(rt);
797
798 if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_NO)
799 return 0;
800
801 r = sd_ndisc_router_get_address(rt, &router);
802 if (r < 0)
803 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
804
805 r = sd_ndisc_router_dnssl_get_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
806 if (r < 0)
807 return log_link_warning_errno(link, r, "Failed to get DNSSL lifetime: %m");
808
809 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
810 if (r < 0)
811 return log_link_warning_errno(link, r, "Failed to get DNSSL addresses: %m");
812
813 STRV_FOREACH(j, l) {
814 _cleanup_free_ NDiscDNSSL *s = NULL;
815 NDiscDNSSL *dnssl;
816
817 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1);
818 if (!s)
819 return log_oom();
820
821 strcpy(NDISC_DNSSL_DOMAIN(s), *j);
822
823 if (lifetime_usec == 0) {
824 /* The entry is outdated. */
825 free(set_remove(link->ndisc_dnssl, s));
826 updated = true;
827 continue;
828 }
829
830 dnssl = set_get(link->ndisc_dnssl, s);
831 if (dnssl) {
832 dnssl->router = router;
833 dnssl->lifetime_usec = lifetime_usec;
834 continue;
835 }
836
837 if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX) {
838 if (!logged_about_too_many)
839 log_link_warning(link, "Too many DNSSL records per link. Only first %u records will be used.", NDISC_DNSSL_MAX);
840 logged_about_too_many = true;
841 continue;
842 }
843
844 s->router = router;
845 s->lifetime_usec = lifetime_usec;
846
847 r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
848 if (r < 0)
849 return log_oom();
850 assert(r > 0);
851
852 updated = true;
853 }
854
855 if (updated)
856 link_dirty(link);
857
858 return 0;
859 }
860
861 static NDiscCaptivePortal* ndisc_captive_portal_free(NDiscCaptivePortal *x) {
862 if (!x)
863 return NULL;
864
865 free(x->captive_portal);
866 return mfree(x);
867 }
868
869 DEFINE_TRIVIAL_CLEANUP_FUNC(NDiscCaptivePortal*, ndisc_captive_portal_free);
870
871 static void ndisc_captive_portal_hash_func(const NDiscCaptivePortal *x, struct siphash *state) {
872 assert(x);
873 siphash24_compress_string(x->captive_portal, state);
874 }
875
876 static int ndisc_captive_portal_compare_func(const NDiscCaptivePortal *a, const NDiscCaptivePortal *b) {
877 assert(a);
878 assert(b);
879 return strcmp_ptr(a->captive_portal, b->captive_portal);
880 }
881
882 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
883 ndisc_captive_portal_hash_ops,
884 NDiscCaptivePortal,
885 ndisc_captive_portal_hash_func,
886 ndisc_captive_portal_compare_func,
887 ndisc_captive_portal_free);
888
889 static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt) {
890 _cleanup_(ndisc_captive_portal_freep) NDiscCaptivePortal *new_entry = NULL;
891 _cleanup_free_ char *captive_portal = NULL;
892 usec_t lifetime_usec;
893 NDiscCaptivePortal *exist;
894 struct in6_addr router;
895 const char *uri;
896 size_t len;
897 int r;
898
899 assert(link);
900 assert(link->network);
901 assert(rt);
902
903 if (!link->network->ipv6_accept_ra_use_captive_portal)
904 return 0;
905
906 r = sd_ndisc_router_get_address(rt, &router);
907 if (r < 0)
908 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
909
910 /* RFC 4861 section 4.2. states that the lifetime in the message header should be used only for the
911 * default gateway, but the captive portal option does not have a lifetime field, hence, we use the
912 * main lifetime for the portal. */
913 r = sd_ndisc_router_get_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
914 if (r < 0)
915 return log_link_warning_errno(link, r, "Failed to get lifetime of RA message: %m");
916
917 r = sd_ndisc_router_captive_portal_get_uri(rt, &uri, &len);
918 if (r < 0)
919 return log_link_warning_errno(link, r, "Failed to get captive portal from RA: %m");
920
921 if (len == 0)
922 return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBADMSG), "Received empty captive portal, ignoring.");
923
924 r = make_cstring(uri, len, MAKE_CSTRING_REFUSE_TRAILING_NUL, &captive_portal);
925 if (r < 0)
926 return log_link_warning_errno(link, r, "Failed to convert captive portal URI: %m");
927
928 if (!in_charset(captive_portal, URI_VALID))
929 return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBADMSG), "Received invalid captive portal, ignoring.");
930
931 if (lifetime_usec == 0) {
932 /* Drop the portal with zero lifetime. */
933 ndisc_captive_portal_free(set_remove(link->ndisc_captive_portals,
934 &(NDiscCaptivePortal) {
935 .captive_portal = captive_portal,
936 }));
937 return 0;
938 }
939
940 exist = set_get(link->ndisc_captive_portals,
941 &(NDiscCaptivePortal) {
942 .captive_portal = captive_portal,
943 });
944 if (exist) {
945 /* update existing entry */
946 exist->router = router;
947 exist->lifetime_usec = lifetime_usec;
948 return 1;
949 }
950
951 if (set_size(link->ndisc_captive_portals) >= NDISC_CAPTIVE_PORTAL_MAX) {
952 NDiscCaptivePortal *c, *target = NULL;
953
954 /* Find the portal who has the minimal lifetime and drop it to store new one. */
955 SET_FOREACH(c, link->ndisc_captive_portals)
956 if (!target || c->lifetime_usec < target->lifetime_usec)
957 target = c;
958
959 assert(target);
960 assert(set_remove(link->ndisc_captive_portals, target) == target);
961 ndisc_captive_portal_free(target);
962 }
963
964 new_entry = new(NDiscCaptivePortal, 1);
965 if (!new_entry)
966 return log_oom();
967
968 *new_entry = (NDiscCaptivePortal) {
969 .router = router,
970 .lifetime_usec = lifetime_usec,
971 .captive_portal = TAKE_PTR(captive_portal),
972 };
973
974 r = set_ensure_put(&link->ndisc_captive_portals, &ndisc_captive_portal_hash_ops, new_entry);
975 if (r < 0)
976 return log_oom();
977 assert(r > 0);
978 TAKE_PTR(new_entry);
979
980 link_dirty(link);
981 return 1;
982 }
983
984 static void ndisc_pref64_hash_func(const NDiscPREF64 *x, struct siphash *state) {
985 assert(x);
986
987 siphash24_compress_typesafe(x->prefix_len, state);
988 siphash24_compress_typesafe(x->prefix, state);
989 }
990
991 static int ndisc_pref64_compare_func(const NDiscPREF64 *a, const NDiscPREF64 *b) {
992 int r;
993
994 assert(a);
995 assert(b);
996
997 r = CMP(a->prefix_len, b->prefix_len);
998 if (r != 0)
999 return r;
1000
1001 return memcmp(&a->prefix, &b->prefix, sizeof(a->prefix));
1002 }
1003
1004 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1005 ndisc_pref64_hash_ops,
1006 NDiscPREF64,
1007 ndisc_pref64_hash_func,
1008 ndisc_pref64_compare_func,
1009 mfree);
1010
1011 static int ndisc_router_process_pref64(Link *link, sd_ndisc_router *rt) {
1012 _cleanup_free_ NDiscPREF64 *new_entry = NULL;
1013 usec_t lifetime_usec;
1014 struct in6_addr a, router;
1015 unsigned prefix_len;
1016 NDiscPREF64 *exist;
1017 int r;
1018
1019 assert(link);
1020 assert(link->network);
1021 assert(rt);
1022
1023 if (!link->network->ipv6_accept_ra_use_pref64)
1024 return 0;
1025
1026 r = sd_ndisc_router_get_address(rt, &router);
1027 if (r < 0)
1028 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
1029
1030 r = sd_ndisc_router_prefix64_get_prefix(rt, &a);
1031 if (r < 0)
1032 return log_link_warning_errno(link, r, "Failed to get pref64 prefix: %m");
1033
1034 r = sd_ndisc_router_prefix64_get_prefixlen(rt, &prefix_len);
1035 if (r < 0)
1036 return log_link_warning_errno(link, r, "Failed to get pref64 prefix length: %m");
1037
1038 r = sd_ndisc_router_prefix64_get_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
1039 if (r < 0)
1040 return log_link_warning_errno(link, r, "Failed to get pref64 prefix lifetime: %m");
1041
1042 if (lifetime_usec == 0) {
1043 free(set_remove(link->ndisc_pref64,
1044 &(NDiscPREF64) {
1045 .prefix = a,
1046 .prefix_len = prefix_len
1047 }));
1048 return 0;
1049 }
1050
1051 exist = set_get(link->ndisc_pref64,
1052 &(NDiscPREF64) {
1053 .prefix = a,
1054 .prefix_len = prefix_len
1055 });
1056 if (exist) {
1057 /* update existing entry */
1058 exist->router = router;
1059 exist->lifetime_usec = lifetime_usec;
1060 return 0;
1061 }
1062
1063 if (set_size(link->ndisc_pref64) >= NDISC_PREF64_MAX) {
1064 log_link_debug(link, "Too many PREF64 records received. Only first %u records will be used.", NDISC_PREF64_MAX);
1065 return 0;
1066 }
1067
1068 new_entry = new(NDiscPREF64, 1);
1069 if (!new_entry)
1070 return log_oom();
1071
1072 *new_entry = (NDiscPREF64) {
1073 .router = router,
1074 .lifetime_usec = lifetime_usec,
1075 .prefix = a,
1076 .prefix_len = prefix_len,
1077 };
1078
1079 r = set_ensure_put(&link->ndisc_pref64, &ndisc_pref64_hash_ops, new_entry);
1080 if (r < 0)
1081 return log_oom();
1082
1083 assert(r > 0);
1084 TAKE_PTR(new_entry);
1085
1086 return 0;
1087 }
1088
1089 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
1090 size_t n_captive_portal = 0;
1091 int r;
1092
1093 assert(link);
1094 assert(link->network);
1095 assert(rt);
1096
1097 for (r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
1098 uint8_t type;
1099
1100 if (r < 0)
1101 return log_link_warning_errno(link, r, "Failed to iterate through options: %m");
1102 if (r == 0) /* EOF */
1103 return 0;
1104
1105 r = sd_ndisc_router_option_get_type(rt, &type);
1106 if (r < 0)
1107 return log_link_warning_errno(link, r, "Failed to get RA option type: %m");
1108
1109 switch (type) {
1110 case SD_NDISC_OPTION_PREFIX_INFORMATION:
1111 r = ndisc_router_process_prefix(link, rt);
1112 break;
1113
1114 case SD_NDISC_OPTION_ROUTE_INFORMATION:
1115 r = ndisc_router_process_route(link, rt);
1116 break;
1117
1118 case SD_NDISC_OPTION_RDNSS:
1119 r = ndisc_router_process_rdnss(link, rt);
1120 break;
1121
1122 case SD_NDISC_OPTION_DNSSL:
1123 r = ndisc_router_process_dnssl(link, rt);
1124 break;
1125 case SD_NDISC_OPTION_CAPTIVE_PORTAL:
1126 if (n_captive_portal > 0) {
1127 if (n_captive_portal == 1)
1128 log_link_notice(link, "Received RA with multiple captive portals, only using the first one.");
1129
1130 n_captive_portal++;
1131 continue;
1132 }
1133 r = ndisc_router_process_captive_portal(link, rt);
1134 if (r > 0)
1135 n_captive_portal++;
1136 break;
1137 case SD_NDISC_OPTION_PREF64:
1138 r = ndisc_router_process_pref64(link, rt);
1139 break;
1140 }
1141 if (r < 0 && r != -EBADMSG)
1142 return r;
1143 }
1144 }
1145
1146 static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
1147 bool updated = false;
1148 NDiscDNSSL *dnssl;
1149 NDiscRDNSS *rdnss;
1150 NDiscCaptivePortal *cp;
1151 NDiscPREF64 *p64;
1152 Address *address;
1153 Route *route;
1154 int r, ret = 0;
1155
1156 assert(link);
1157
1158 /* If an address or friends is already assigned, but not valid anymore, then refuse to update it,
1159 * and let's immediately remove it.
1160 * See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by honoring all
1161 * valid lifetimes to improve the reaction of SLAAC to renumbering events.
1162 * See draft-ietf-6man-slaac-renum-02, section 4.2. */
1163
1164 SET_FOREACH(route, link->routes) {
1165 if (route->source != NETWORK_CONFIG_SOURCE_NDISC)
1166 continue;
1167
1168 if (route->lifetime_usec >= timestamp_usec)
1169 continue; /* the route is still valid */
1170
1171 r = route_remove_and_drop(route);
1172 if (r < 0)
1173 RET_GATHER(ret, log_link_warning_errno(link, r, "Failed to remove outdated SLAAC route, ignoring: %m"));
1174 }
1175
1176 SET_FOREACH(address, link->addresses) {
1177 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
1178 continue;
1179
1180 if (address->lifetime_valid_usec >= timestamp_usec)
1181 continue; /* the address is still valid */
1182
1183 r = address_remove_and_cancel(address, link);
1184 if (r < 0)
1185 RET_GATHER(ret, log_link_warning_errno(link, r, "Failed to remove outdated SLAAC address, ignoring: %m"));
1186 }
1187
1188 SET_FOREACH(rdnss, link->ndisc_rdnss) {
1189 if (rdnss->lifetime_usec >= timestamp_usec)
1190 continue; /* the DNS server is still valid */
1191
1192 free(set_remove(link->ndisc_rdnss, rdnss));
1193 updated = true;
1194 }
1195
1196 SET_FOREACH(dnssl, link->ndisc_dnssl) {
1197 if (dnssl->lifetime_usec >= timestamp_usec)
1198 continue; /* the DNS domain is still valid */
1199
1200 free(set_remove(link->ndisc_dnssl, dnssl));
1201 updated = true;
1202 }
1203
1204 SET_FOREACH(cp, link->ndisc_captive_portals) {
1205 if (cp->lifetime_usec >= timestamp_usec)
1206 continue; /* the captive portal is still valid */
1207
1208 ndisc_captive_portal_free(set_remove(link->ndisc_captive_portals, cp));
1209 updated = true;
1210 }
1211
1212 SET_FOREACH(p64, link->ndisc_pref64) {
1213 if (p64->lifetime_usec >= timestamp_usec)
1214 continue; /* the pref64 prefix is still valid */
1215
1216 free(set_remove(link->ndisc_pref64, p64));
1217 /* The pref64 prefix is not exported through the state file, hence it is not necessary to set
1218 * the 'updated' flag. */
1219 }
1220
1221 if (updated)
1222 link_dirty(link);
1223
1224 return ret;
1225 }
1226
1227 static int ndisc_setup_expire(Link *link);
1228
1229 static int ndisc_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
1230 Link *link = ASSERT_PTR(userdata);
1231 usec_t now_usec;
1232
1233 assert(link->manager);
1234
1235 assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
1236
1237 (void) ndisc_drop_outdated(link, now_usec);
1238 (void) ndisc_setup_expire(link);
1239 return 0;
1240 }
1241
1242 static int ndisc_setup_expire(Link *link) {
1243 usec_t lifetime_usec = USEC_INFINITY;
1244 NDiscCaptivePortal *cp;
1245 NDiscDNSSL *dnssl;
1246 NDiscRDNSS *rdnss;
1247 NDiscPREF64 *p64;
1248 Address *address;
1249 Route *route;
1250 int r;
1251
1252 assert(link);
1253 assert(link->manager);
1254
1255 SET_FOREACH(route, link->routes) {
1256 if (route->source != NETWORK_CONFIG_SOURCE_NDISC)
1257 continue;
1258
1259 if (!route_exists(route))
1260 continue;
1261
1262 lifetime_usec = MIN(lifetime_usec, route->lifetime_usec);
1263 }
1264
1265 SET_FOREACH(address, link->addresses) {
1266 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
1267 continue;
1268
1269 if (!address_exists(address))
1270 continue;
1271
1272 lifetime_usec = MIN(lifetime_usec, address->lifetime_valid_usec);
1273 }
1274
1275 SET_FOREACH(rdnss, link->ndisc_rdnss)
1276 lifetime_usec = MIN(lifetime_usec, rdnss->lifetime_usec);
1277
1278 SET_FOREACH(dnssl, link->ndisc_dnssl)
1279 lifetime_usec = MIN(lifetime_usec, dnssl->lifetime_usec);
1280
1281 SET_FOREACH(cp, link->ndisc_captive_portals)
1282 lifetime_usec = MIN(lifetime_usec, cp->lifetime_usec);
1283
1284 SET_FOREACH(p64, link->ndisc_pref64)
1285 lifetime_usec = MIN(lifetime_usec, p64->lifetime_usec);
1286
1287 if (lifetime_usec == USEC_INFINITY)
1288 return 0;
1289
1290 r = event_reset_time(link->manager->event, &link->ndisc_expire, CLOCK_BOOTTIME,
1291 lifetime_usec, 0, ndisc_expire_handler, link, 0, "ndisc-expiration", true);
1292 if (r < 0)
1293 return log_link_warning_errno(link, r, "Failed to update expiration timer for ndisc: %m");
1294
1295 return 0;
1296 }
1297
1298 static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) {
1299 int r;
1300
1301 assert(link);
1302 assert(link->network);
1303
1304 switch (link->network->ipv6_accept_ra_start_dhcp6_client) {
1305 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO:
1306 return 0;
1307
1308 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES: {
1309 uint64_t flags;
1310
1311 r = sd_ndisc_router_get_flags(rt, &flags);
1312 if (r < 0)
1313 return log_link_warning_errno(link, r, "Failed to get RA flags: %m");
1314
1315 if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) == 0)
1316 return 0;
1317
1318 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags.
1319 * Note, if both "managed" and "other configuration" bits are set, then ignore
1320 * "other configuration" bit. See RFC 4861. */
1321 r = dhcp6_start_on_ra(link, !(flags & ND_RA_FLAG_MANAGED));
1322 break;
1323 }
1324 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS:
1325 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in solicit mode
1326 * even if the router flags have neither M nor O flags. */
1327 r = dhcp6_start_on_ra(link, /* information_request = */ false);
1328 break;
1329
1330 default:
1331 assert_not_reached();
1332 }
1333
1334 if (r < 0)
1335 return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
1336
1337 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
1338 return 0;
1339 }
1340
1341 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
1342 struct in6_addr router;
1343 usec_t timestamp_usec;
1344 int r;
1345
1346 assert(link);
1347 assert(link->network);
1348 assert(link->manager);
1349 assert(rt);
1350
1351 r = sd_ndisc_router_get_address(rt, &router);
1352 if (r == -ENODATA) {
1353 log_link_debug(link, "Received RA without router address, ignoring.");
1354 return 0;
1355 }
1356 if (r < 0)
1357 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
1358
1359 if (in6_prefix_is_filtered(&router, 128, link->network->ndisc_allow_listed_router, link->network->ndisc_deny_listed_router)) {
1360 if (DEBUG_LOGGING) {
1361 if (!set_isempty(link->network->ndisc_allow_listed_router))
1362 log_link_debug(link, "Router %s is not in allow list, ignoring.", IN6_ADDR_TO_STRING(&router));
1363 else
1364 log_link_debug(link, "Router %s is in deny list, ignoring.", IN6_ADDR_TO_STRING(&router));
1365 }
1366 return 0;
1367 }
1368
1369 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
1370 if (r == -ENODATA) {
1371 log_link_debug(link, "Received RA without timestamp, ignoring.");
1372 return 0;
1373 }
1374 if (r < 0)
1375 return r;
1376
1377 r = ndisc_drop_outdated(link, timestamp_usec);
1378 if (r < 0)
1379 return r;
1380
1381 r = ndisc_start_dhcp6_client(link, rt);
1382 if (r < 0)
1383 return r;
1384
1385 r = ndisc_router_process_default(link, rt);
1386 if (r < 0)
1387 return r;
1388
1389 r = ndisc_router_process_icmp6_ratelimit(link, rt);
1390 if (r < 0)
1391 return r;
1392
1393 r = ndisc_router_process_retransmission_time(link, rt);
1394 if (r < 0)
1395 return r;
1396
1397 r = ndisc_router_process_options(link, rt);
1398 if (r < 0)
1399 return r;
1400
1401 r = ndisc_setup_expire(link);
1402 if (r < 0)
1403 return r;
1404
1405 if (link->ndisc_messages == 0)
1406 link->ndisc_configured = true;
1407 else
1408 log_link_debug(link, "Setting SLAAC addresses and router.");
1409
1410 if (!link->ndisc_configured)
1411 link_set_state(link, LINK_STATE_CONFIGURING);
1412
1413 link_check_ready(link);
1414 return 0;
1415 }
1416
1417 static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
1418 Link *link = ASSERT_PTR(userdata);
1419 int r;
1420
1421 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1422 return;
1423
1424 switch (event) {
1425
1426 case SD_NDISC_EVENT_ROUTER:
1427 r = ndisc_router_handler(link, rt);
1428 if (r < 0 && r != -EBADMSG) {
1429 link_enter_failed(link);
1430 return;
1431 }
1432 break;
1433
1434 case SD_NDISC_EVENT_TIMEOUT:
1435 log_link_debug(link, "NDisc handler get timeout event");
1436 if (link->ndisc_messages == 0) {
1437 link->ndisc_configured = true;
1438 link_check_ready(link);
1439 }
1440 break;
1441 default:
1442 assert_not_reached();
1443 }
1444 }
1445
1446 static int ndisc_configure(Link *link) {
1447 int r;
1448
1449 assert(link);
1450
1451 if (!link_ipv6_accept_ra_enabled(link))
1452 return 0;
1453
1454 if (link->ndisc)
1455 return -EBUSY; /* Already configured. */
1456
1457 r = sd_ndisc_new(&link->ndisc);
1458 if (r < 0)
1459 return r;
1460
1461 r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
1462 if (r < 0)
1463 return r;
1464
1465 if (link->hw_addr.length == ETH_ALEN) {
1466 r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.ether);
1467 if (r < 0)
1468 return r;
1469 }
1470
1471 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
1472 if (r < 0)
1473 return r;
1474
1475 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
1476 if (r < 0)
1477 return r;
1478
1479 return 0;
1480 }
1481
1482 int ndisc_start(Link *link) {
1483 int r;
1484
1485 assert(link);
1486
1487 if (!link->ndisc || !link->dhcp6_client)
1488 return 0;
1489
1490 if (!link_has_carrier(link))
1491 return 0;
1492
1493 if (in6_addr_is_null(&link->ipv6ll_address))
1494 return 0;
1495
1496 log_link_debug(link, "Discovering IPv6 routers");
1497
1498 r = sd_ndisc_start(link->ndisc);
1499 if (r < 0)
1500 return r;
1501
1502 return 1;
1503 }
1504
1505 static int ndisc_process_request(Request *req, Link *link, void *userdata) {
1506 int r;
1507
1508 assert(link);
1509
1510 if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false))
1511 return 0;
1512
1513 r = ndisc_configure(link);
1514 if (r < 0)
1515 return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Discovery: %m");
1516
1517 r = ndisc_start(link);
1518 if (r < 0)
1519 return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
1520
1521 log_link_debug(link, "IPv6 Router Discovery is configured%s.",
1522 r > 0 ? " and started" : "");
1523 return 1;
1524 }
1525
1526 int link_request_ndisc(Link *link) {
1527 int r;
1528
1529 assert(link);
1530
1531 if (!link_ipv6_accept_ra_enabled(link))
1532 return 0;
1533
1534 if (link->ndisc)
1535 return 0;
1536
1537 r = link_queue_request(link, REQUEST_TYPE_NDISC, ndisc_process_request, NULL);
1538 if (r < 0)
1539 return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m");
1540
1541 log_link_debug(link, "Requested configuring of the IPv6 Router Discovery.");
1542 return 0;
1543 }
1544
1545 int ndisc_stop(Link *link) {
1546 assert(link);
1547
1548 link->ndisc_expire = sd_event_source_disable_unref(link->ndisc_expire);
1549
1550 return sd_ndisc_stop(link->ndisc);
1551 }
1552
1553
1554 void ndisc_flush(Link *link) {
1555 assert(link);
1556
1557 /* Remove all RDNSS, DNSSL, and Captive Portal entries, without exception. */
1558
1559 link->ndisc_rdnss = set_free(link->ndisc_rdnss);
1560 link->ndisc_dnssl = set_free(link->ndisc_dnssl);
1561 link->ndisc_captive_portals = set_free(link->ndisc_captive_portals);
1562 link->ndisc_pref64 = set_free(link->ndisc_pref64);
1563 }
1564
1565 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1566 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1567 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1568 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1569 };
1570
1571 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);
1572
1573 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains, dhcp_use_domains, DHCPUseDomains,
1574 "Failed to parse UseDomains= setting");
1575 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
1576 "Failed to parse DHCPv6Client= setting");