]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
tree-wide: use ASSERT_PTR more
[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 "missing_network.h"
14 #include "networkd-address-generation.h"
15 #include "networkd-address.h"
16 #include "networkd-dhcp6.h"
17 #include "networkd-manager.h"
18 #include "networkd-ndisc.h"
19 #include "networkd-queue.h"
20 #include "networkd-route.h"
21 #include "networkd-state-file.h"
22 #include "string-table.h"
23 #include "string-util.h"
24 #include "strv.h"
25
26 #define NDISC_DNSSL_MAX 64U
27 #define NDISC_RDNSS_MAX 64U
28
29 bool link_ipv6_accept_ra_enabled(Link *link) {
30 assert(link);
31
32 if (!socket_ipv6_is_supported())
33 return false;
34
35 if (link->flags & IFF_LOOPBACK)
36 return false;
37
38 if (link->iftype == ARPHRD_CAN)
39 return false;
40
41 if (!link->network)
42 return false;
43
44 if (!link_may_have_ipv6ll(link, /* check_multicast = */ true))
45 return false;
46
47 assert(link->network->ipv6_accept_ra >= 0);
48 return link->network->ipv6_accept_ra;
49 }
50
51 void network_adjust_ipv6_accept_ra(Network *network) {
52 assert(network);
53
54 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
55 if (network->ipv6_accept_ra > 0)
56 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link-local addressing is disabled or not supported. "
57 "Disabling IPv6AcceptRA=.", network->filename);
58 network->ipv6_accept_ra = false;
59 }
60
61 if (network->ipv6_accept_ra < 0)
62 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
63 network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6);
64
65 /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
66 * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
67 if (!set_isempty(network->ndisc_allow_listed_router))
68 network->ndisc_deny_listed_router = set_free_free(network->ndisc_deny_listed_router);
69 if (!set_isempty(network->ndisc_allow_listed_prefix))
70 network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix);
71 if (!set_isempty(network->ndisc_allow_listed_route_prefix))
72 network->ndisc_deny_listed_route_prefix = set_free_free(network->ndisc_deny_listed_route_prefix);
73 }
74
75 static int ndisc_remove(Link *link, struct in6_addr *router) {
76 bool updated = false;
77 NDiscDNSSL *dnssl;
78 NDiscRDNSS *rdnss;
79 Address *address;
80 Route *route;
81 int k, r = 0;
82
83 assert(link);
84
85 SET_FOREACH(route, link->routes) {
86 if (route->source != NETWORK_CONFIG_SOURCE_NDISC)
87 continue;
88 if (!route_is_marked(route))
89 continue;
90 if (router && !in6_addr_equal(router, &route->provider.in6))
91 continue;
92
93 k = route_remove(route);
94 if (k < 0)
95 r = k;
96
97 route_cancel_request(route, link);
98 }
99
100 SET_FOREACH(address, link->addresses) {
101 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
102 continue;
103 if (!address_is_marked(address))
104 continue;
105 if (router && !in6_addr_equal(router, &address->provider.in6))
106 continue;
107
108 k = address_remove(address);
109 if (k < 0)
110 r = k;
111
112 address_cancel_request(address);
113 }
114
115 SET_FOREACH(rdnss, link->ndisc_rdnss) {
116 if (!rdnss->marked)
117 continue;
118 if (router && !in6_addr_equal(router, &rdnss->router))
119 continue;
120
121 free(set_remove(link->ndisc_rdnss, rdnss));
122 updated = true;
123 }
124
125 SET_FOREACH(dnssl, link->ndisc_dnssl) {
126 if (!dnssl->marked)
127 continue;
128 if (router && !in6_addr_equal(router, &dnssl->router))
129 continue;
130
131 free(set_remove(link->ndisc_dnssl, dnssl));
132 updated = true;
133 }
134
135 if (updated)
136 link_dirty(link);
137
138 return r;
139 }
140
141 static int ndisc_check_ready(Link *link);
142
143 static int ndisc_address_ready_callback(Address *address) {
144 Address *a;
145
146 assert(address);
147 assert(address->link);
148
149 SET_FOREACH(a, address->link->addresses)
150 if (a->source == NETWORK_CONFIG_SOURCE_NDISC)
151 a->callback = NULL;
152
153 return ndisc_check_ready(address->link);
154 }
155
156 static int ndisc_check_ready(Link *link) {
157 bool found = false, ready = false;
158 Address *address;
159 int r;
160
161 assert(link);
162
163 if (link->ndisc_messages > 0) {
164 log_link_debug(link, "%s(): SLAAC addresses and routes are not set.", __func__);
165 return 0;
166 }
167
168 SET_FOREACH(address, link->addresses) {
169 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
170 continue;
171
172 found = true;
173
174 if (address_is_ready(address)) {
175 ready = true;
176 break;
177 }
178 }
179
180 if (found && !ready) {
181 SET_FOREACH(address, link->addresses)
182 if (address->source == NETWORK_CONFIG_SOURCE_NDISC)
183 address->callback = ndisc_address_ready_callback;
184
185 log_link_debug(link, "%s(): no SLAAC address is ready.", __func__);
186 return 0;
187 }
188
189 link->ndisc_configured = true;
190 log_link_debug(link, "SLAAC addresses and routes set.");
191
192 r = ndisc_remove(link, NULL);
193 if (r < 0)
194 return r;
195
196 link_check_ready(link);
197 return 0;
198 }
199
200 static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
201 int r;
202
203 assert(link);
204
205 r = route_configure_handler_internal(rtnl, m, link, "Could not set NDisc route");
206 if (r <= 0)
207 return r;
208
209 r = ndisc_check_ready(link);
210 if (r < 0)
211 link_enter_failed(link);
212
213 return 1;
214 }
215
216 static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
217 _cleanup_(route_freep) Route *route = in;
218 struct in6_addr router;
219 Route *existing;
220 int r;
221
222 assert(route);
223 assert(link);
224 assert(rt);
225
226 r = sd_ndisc_router_get_address(rt, &router);
227 if (r < 0)
228 return r;
229
230 route->source = NETWORK_CONFIG_SOURCE_NDISC;
231 route->provider.in6 = router;
232 if (!route->table_set)
233 route->table = link_get_ipv6_accept_ra_route_table(link);
234 if (!route->priority_set)
235 route->priority = link->network->ipv6_accept_ra_route_metric;
236 if (!route->protocol_set)
237 route->protocol = RTPROT_RA;
238
239 if (route_get(NULL, link, route, &existing) < 0)
240 link->ndisc_configured = false;
241 else
242 route_unmark(existing);
243
244 return link_request_route(link, TAKE_PTR(route), true, &link->ndisc_messages,
245 ndisc_route_handler, NULL);
246 }
247
248 static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
249 int r;
250
251 assert(link);
252
253 r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address");
254 if (r <= 0)
255 return r;
256
257 r = ndisc_check_ready(link);
258 if (r < 0)
259 link_enter_failed(link);
260
261 return 1;
262 }
263
264 static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {
265 _cleanup_(address_freep) Address *address = in;
266 struct in6_addr router;
267 Address *existing;
268 int r;
269
270 assert(address);
271 assert(link);
272 assert(rt);
273
274 r = sd_ndisc_router_get_address(rt, &router);
275 if (r < 0)
276 return r;
277
278 address->source = NETWORK_CONFIG_SOURCE_NDISC;
279 address->provider.in6 = router;
280
281 r = free_and_strdup_warn(&address->netlabel, link->network->ndisc_netlabel);
282 if (r < 0)
283 return r;
284
285 if (address_get(link, address, &existing) < 0)
286 link->ndisc_configured = false;
287 else
288 address_unmark(existing);
289
290 return link_request_address(link, TAKE_PTR(address), true, &link->ndisc_messages,
291 ndisc_address_handler, NULL);
292 }
293
294 static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
295 usec_t lifetime_usec, timestamp_usec;
296 struct in6_addr gateway;
297 uint16_t lifetime_sec;
298 unsigned preference;
299 uint32_t mtu = 0;
300 int r;
301
302 assert(link);
303 assert(link->network);
304 assert(rt);
305
306 if (!link->network->ipv6_accept_ra_use_gateway &&
307 hashmap_isempty(link->network->routes_by_section))
308 return 0;
309
310 r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec);
311 if (r < 0)
312 return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
313
314 if (lifetime_sec == 0) /* not a default router */
315 return 0;
316
317 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
318 if (r < 0)
319 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
320
321 lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec);
322
323 r = sd_ndisc_router_get_address(rt, &gateway);
324 if (r < 0)
325 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
326
327 if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
328 if (DEBUG_LOGGING)
329 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
330 IN6_ADDR_TO_STRING(&gateway));
331 return 0;
332 }
333
334 r = sd_ndisc_router_get_preference(rt, &preference);
335 if (r < 0)
336 return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
337
338 if (link->network->ipv6_accept_ra_use_mtu) {
339 r = sd_ndisc_router_get_mtu(rt, &mtu);
340 if (r < 0 && r != -ENODATA)
341 return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m");
342 }
343
344 if (link->network->ipv6_accept_ra_use_gateway) {
345 _cleanup_(route_freep) Route *route = NULL;
346
347 r = route_new(&route);
348 if (r < 0)
349 return log_oom();
350
351 route->family = AF_INET6;
352 route->pref = preference;
353 route->gw_family = AF_INET6;
354 route->gw.in6 = gateway;
355 route->lifetime_usec = lifetime_usec;
356 route->mtu = mtu;
357
358 r = ndisc_request_route(TAKE_PTR(route), link, rt);
359 if (r < 0)
360 return log_link_error_errno(link, r, "Could not request default route: %m");
361 }
362
363 Route *route_gw;
364 HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
365 _cleanup_(route_freep) Route *route = NULL;
366
367 if (!route_gw->gateway_from_dhcp_or_ra)
368 continue;
369
370 if (route_gw->gw_family != AF_INET6)
371 continue;
372
373 r = route_dup(route_gw, &route);
374 if (r < 0)
375 return r;
376
377 route->gw.in6 = gateway;
378 if (!route->pref_set)
379 route->pref = preference;
380 route->lifetime_usec = lifetime_usec;
381 if (route->mtu == 0)
382 route->mtu = mtu;
383
384 r = ndisc_request_route(TAKE_PTR(route), link, rt);
385 if (r < 0)
386 return log_link_error_errno(link, r, "Could not request gateway: %m");
387 }
388
389 return 0;
390 }
391
392 static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
393 uint32_t lifetime_valid_sec, lifetime_preferred_sec;
394 usec_t lifetime_valid_usec, lifetime_preferred_usec, timestamp_usec;
395 _cleanup_set_free_ Set *addresses = NULL;
396 struct in6_addr prefix, *a;
397 unsigned prefixlen;
398 int r;
399
400 assert(link);
401 assert(link->network);
402 assert(rt);
403
404 if (!link->network->ipv6_accept_ra_use_autonomous_prefix)
405 return 0;
406
407 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
408 if (r < 0)
409 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
410
411 r = sd_ndisc_router_prefix_get_address(rt, &prefix);
412 if (r < 0)
413 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
414
415 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
416 if (r < 0)
417 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
418
419 /* ndisc_generate_addresses() below requires the prefix length <= 64. */
420 if (prefixlen > 64) {
421 log_link_debug(link, "Prefix is longer than 64, ignoring autonomous prefix %s.",
422 IN6_ADDR_PREFIX_TO_STRING(&prefix, prefixlen));
423 return 0;
424 }
425
426 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid_sec);
427 if (r < 0)
428 return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
429
430 if (lifetime_valid_sec == 0) {
431 log_link_debug(link, "Ignoring prefix as its valid lifetime is zero.");
432 return 0;
433 }
434
435 r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred_sec);
436 if (r < 0)
437 return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
438
439 /* The preferred lifetime is never greater than the valid lifetime */
440 if (lifetime_preferred_sec > lifetime_valid_sec)
441 return 0;
442
443 lifetime_valid_usec = sec_to_usec(lifetime_valid_sec, timestamp_usec);
444 lifetime_preferred_usec = sec_to_usec(lifetime_preferred_sec, timestamp_usec);
445
446 r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses);
447 if (r < 0)
448 return log_link_error_errno(link, r, "Failed to generate SLAAC addresses: %m");
449
450 SET_FOREACH(a, addresses) {
451 _cleanup_(address_freep) Address *address = NULL;
452 Address *e;
453
454 r = address_new(&address);
455 if (r < 0)
456 return log_oom();
457
458 address->family = AF_INET6;
459 address->in_addr.in6 = *a;
460 address->prefixlen = prefixlen;
461 address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
462 address->lifetime_valid_usec = lifetime_valid_usec;
463 address->lifetime_preferred_usec = lifetime_preferred_usec;
464
465 /* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by
466 * honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events.
467 * See draft-ietf-6man-slaac-renum-02, section 4.2. */
468 r = address_get(link, address, &e);
469 if (r > 0) {
470 /* If the address is already assigned, but not valid anymore, then refuse to
471 * update the address, and it will be removed. */
472 if (e->lifetime_valid_usec < timestamp_usec)
473 continue;
474 }
475
476 r = ndisc_request_address(TAKE_PTR(address), link, rt);
477 if (r < 0)
478 return log_link_error_errno(link, r, "Could not request SLAAC address: %m");
479 }
480
481 return 0;
482 }
483
484 static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
485 _cleanup_(route_freep) Route *route = NULL;
486 usec_t timestamp_usec;
487 uint32_t lifetime_sec;
488 unsigned prefixlen;
489 int r;
490
491 assert(link);
492 assert(link->network);
493 assert(rt);
494
495 if (!link->network->ipv6_accept_ra_use_onlink_prefix)
496 return 0;
497
498 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec);
499 if (r < 0)
500 return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
501
502 if (lifetime_sec == 0)
503 return 0;
504
505 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
506 if (r < 0)
507 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
508
509 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
510 if (r < 0)
511 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
512
513 r = route_new(&route);
514 if (r < 0)
515 return log_oom();
516
517 route->family = AF_INET6;
518 route->flags = RTM_F_PREFIX;
519 route->dst_prefixlen = prefixlen;
520 route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
521
522 r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
523 if (r < 0)
524 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
525
526 r = ndisc_request_route(TAKE_PTR(route), link, rt);
527 if (r < 0)
528 return log_link_error_errno(link, r, "Could not request prefix route: %m");
529
530 return 0;
531 }
532
533 static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) {
534 unsigned prefixlen;
535 struct in6_addr a;
536 uint8_t flags;
537 int r;
538
539 assert(link);
540 assert(link->network);
541 assert(rt);
542
543 r = sd_ndisc_router_prefix_get_address(rt, &a);
544 if (r < 0)
545 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
546
547 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
548 if (r < 0)
549 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
550
551 if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) {
552 if (DEBUG_LOGGING)
553 log_link_debug(link, "Prefix '%s' is %s, ignoring",
554 !set_isempty(link->network->ndisc_allow_listed_prefix) ? "not in allow list"
555 : "in deny list",
556 IN6_ADDR_PREFIX_TO_STRING(&a, prefixlen));
557 return 0;
558 }
559
560 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
561 if (r < 0)
562 return log_link_error_errno(link, r, "Failed to get RA prefix flags: %m");
563
564 if (FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) {
565 r = ndisc_router_process_onlink_prefix(link, rt);
566 if (r < 0)
567 return r;
568 }
569
570 if (FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) {
571 r = ndisc_router_process_autonomous_prefix(link, rt);
572 if (r < 0)
573 return r;
574 }
575
576 return 0;
577 }
578
579 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
580 _cleanup_(route_freep) Route *route = NULL;
581 unsigned preference, prefixlen;
582 struct in6_addr gateway, dst;
583 uint32_t lifetime_sec;
584 usec_t timestamp_usec;
585 int r;
586
587 assert(link);
588
589 if (!link->network->ipv6_accept_ra_use_route_prefix)
590 return 0;
591
592 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime_sec);
593 if (r < 0)
594 return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m");
595
596 if (lifetime_sec == 0)
597 return 0;
598
599 r = sd_ndisc_router_route_get_address(rt, &dst);
600 if (r < 0)
601 return log_link_error_errno(link, r, "Failed to get route destination address: %m");
602
603 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
604 if (r < 0)
605 return log_link_error_errno(link, r, "Failed to get route prefix length: %m");
606
607 if (in6_addr_is_null(&dst) && prefixlen == 0) {
608 log_link_debug(link, "Route prefix is ::/0, ignoring");
609 return 0;
610 }
611
612 if (in6_prefix_is_filtered(&dst, prefixlen,
613 link->network->ndisc_allow_listed_route_prefix,
614 link->network->ndisc_deny_listed_route_prefix)) {
615
616 if (DEBUG_LOGGING)
617 log_link_debug(link, "Route prefix %s is %s, ignoring",
618 !set_isempty(link->network->ndisc_allow_listed_route_prefix) ? "not in allow list"
619 : "in deny list",
620 IN6_ADDR_PREFIX_TO_STRING(&dst, prefixlen));
621 return 0;
622 }
623
624 r = sd_ndisc_router_get_address(rt, &gateway);
625 if (r < 0)
626 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
627
628 if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
629 if (DEBUG_LOGGING)
630 log_link_debug(link, "Advertised route gateway %s is local to the link, ignoring route",
631 IN6_ADDR_TO_STRING(&gateway));
632 return 0;
633 }
634
635 r = sd_ndisc_router_route_get_preference(rt, &preference);
636 if (r < 0)
637 return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
638
639 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
640 if (r < 0)
641 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
642
643 r = route_new(&route);
644 if (r < 0)
645 return log_oom();
646
647 route->family = AF_INET6;
648 route->pref = preference;
649 route->gw.in6 = gateway;
650 route->gw_family = AF_INET6;
651 route->dst.in6 = dst;
652 route->dst_prefixlen = prefixlen;
653 route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
654
655 r = ndisc_request_route(TAKE_PTR(route), link, rt);
656 if (r < 0)
657 return log_link_error_errno(link, r, "Could not request additional route: %m");
658
659 return 0;
660 }
661
662 static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
663 siphash24_compress(&x->address, sizeof(x->address), state);
664 }
665
666 static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
667 return memcmp(&a->address, &b->address, sizeof(a->address));
668 }
669
670 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
671 ndisc_rdnss_hash_ops,
672 NDiscRDNSS,
673 ndisc_rdnss_hash_func,
674 ndisc_rdnss_compare_func,
675 free);
676
677 static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
678 usec_t lifetime_usec, timestamp_usec;
679 uint32_t lifetime_sec;
680 const struct in6_addr *a;
681 struct in6_addr router;
682 bool updated = false;
683 int n, r;
684
685 assert(link);
686 assert(link->network);
687 assert(rt);
688
689 if (!link->network->ipv6_accept_ra_use_dns)
690 return 0;
691
692 r = sd_ndisc_router_get_address(rt, &router);
693 if (r < 0)
694 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
695
696 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
697 if (r < 0)
698 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
699
700 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime_sec);
701 if (r < 0)
702 return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
703
704 if (lifetime_sec == 0)
705 return 0;
706
707 lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
708
709 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
710 if (n < 0)
711 return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
712
713 if (n >= (int) NDISC_RDNSS_MAX) {
714 log_link_warning(link, "Too many RDNSS records per link. Only first %u records will be used.", NDISC_RDNSS_MAX);
715 n = NDISC_RDNSS_MAX;
716 }
717
718 for (int j = 0; j < n; j++) {
719 _cleanup_free_ NDiscRDNSS *x = NULL;
720 NDiscRDNSS *rdnss, d = {
721 .address = a[j],
722 };
723
724 rdnss = set_get(link->ndisc_rdnss, &d);
725 if (rdnss) {
726 rdnss->marked = false;
727 rdnss->router = router;
728 rdnss->lifetime_usec = lifetime_usec;
729 continue;
730 }
731
732 x = new(NDiscRDNSS, 1);
733 if (!x)
734 return log_oom();
735
736 *x = (NDiscRDNSS) {
737 .address = a[j],
738 .router = router,
739 .lifetime_usec = lifetime_usec,
740 };
741
742 r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
743 if (r < 0)
744 return log_oom();
745 assert(r > 0);
746
747 updated = true;
748 }
749
750 if (updated)
751 link_dirty(link);
752
753 return 0;
754 }
755
756 static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
757 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x), state);
758 }
759
760 static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
761 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
762 }
763
764 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
765 ndisc_dnssl_hash_ops,
766 NDiscDNSSL,
767 ndisc_dnssl_hash_func,
768 ndisc_dnssl_compare_func,
769 free);
770
771 static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
772 _cleanup_strv_free_ char **l = NULL;
773 usec_t lifetime_usec, timestamp_usec;
774 struct in6_addr router;
775 uint32_t lifetime_sec;
776 bool updated = false;
777 int r;
778
779 assert(link);
780 assert(link->network);
781 assert(rt);
782
783 if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_NO)
784 return 0;
785
786 r = sd_ndisc_router_get_address(rt, &router);
787 if (r < 0)
788 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
789
790 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
791 if (r < 0)
792 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
793
794 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime_sec);
795 if (r < 0)
796 return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
797
798 if (lifetime_sec == 0)
799 return 0;
800
801 lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
802
803 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
804 if (r < 0)
805 return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
806
807 if (strv_length(l) >= NDISC_DNSSL_MAX) {
808 log_link_warning(link, "Too many DNSSL records per link. Only first %u records will be used.", NDISC_DNSSL_MAX);
809 STRV_FOREACH(j, l + NDISC_DNSSL_MAX)
810 *j = mfree(*j);
811 }
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 dnssl = set_get(link->ndisc_dnssl, s);
824 if (dnssl) {
825 dnssl->marked = false;
826 dnssl->router = router;
827 dnssl->lifetime_usec = lifetime_usec;
828 continue;
829 }
830
831 s->router = router;
832 s->lifetime_usec = lifetime_usec;
833
834 r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
835 if (r < 0)
836 return log_oom();
837 assert(r > 0);
838
839 updated = true;
840 }
841
842 if (updated)
843 link_dirty(link);
844
845 return 0;
846 }
847
848 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
849 int r;
850
851 assert(link);
852 assert(link->network);
853 assert(rt);
854
855 for (r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
856 uint8_t type;
857
858 if (r < 0)
859 return log_link_error_errno(link, r, "Failed to iterate through options: %m");
860 if (r == 0) /* EOF */
861 return 0;
862
863 r = sd_ndisc_router_option_get_type(rt, &type);
864 if (r < 0)
865 return log_link_error_errno(link, r, "Failed to get RA option type: %m");
866
867 switch (type) {
868
869 case SD_NDISC_OPTION_PREFIX_INFORMATION:
870 r = ndisc_router_process_prefix(link, rt);
871 if (r < 0)
872 return r;
873 break;
874
875 case SD_NDISC_OPTION_ROUTE_INFORMATION:
876 r = ndisc_router_process_route(link, rt);
877 if (r < 0)
878 return r;
879 break;
880
881 case SD_NDISC_OPTION_RDNSS:
882 r = ndisc_router_process_rdnss(link, rt);
883 if (r < 0)
884 return r;
885 break;
886
887 case SD_NDISC_OPTION_DNSSL:
888 r = ndisc_router_process_dnssl(link, rt);
889 if (r < 0)
890 return r;
891 break;
892 }
893 }
894 }
895
896 static void ndisc_mark(Link *link, const struct in6_addr *router) {
897 NDiscRDNSS *rdnss;
898 NDiscDNSSL *dnssl;
899
900 assert(link);
901 assert(router);
902
903 link_mark_addresses(link, NETWORK_CONFIG_SOURCE_NDISC, router);
904 link_mark_routes(link, NETWORK_CONFIG_SOURCE_NDISC, router);
905
906 SET_FOREACH(rdnss, link->ndisc_rdnss)
907 if (in6_addr_equal(&rdnss->router, router))
908 rdnss->marked = true;
909
910 SET_FOREACH(dnssl, link->ndisc_dnssl)
911 if (in6_addr_equal(&dnssl->router, router))
912 dnssl->marked = true;
913 }
914
915 static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) {
916 int r;
917
918 assert(link);
919 assert(link->network);
920
921 switch (link->network->ipv6_accept_ra_start_dhcp6_client) {
922 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO:
923 return 0;
924
925 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES: {
926 uint64_t flags;
927
928 r = sd_ndisc_router_get_flags(rt, &flags);
929 if (r < 0)
930 return log_link_warning_errno(link, r, "Failed to get RA flags: %m");
931
932 if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) == 0)
933 return 0;
934
935 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags.
936 * Note, if both "managed" and "other configuration" bits are set, then ignore
937 * "other configuration" bit. See RFC 4861. */
938 r = dhcp6_start_on_ra(link, !(flags & ND_RA_FLAG_MANAGED));
939 break;
940 }
941 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS:
942 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in solicit mode
943 * even if the router flags have neither M nor O flags. */
944 r = dhcp6_start_on_ra(link, /* information_request = */ false);
945 break;
946
947 default:
948 assert_not_reached();
949 }
950
951 if (r < 0)
952 return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
953
954 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
955 return 0;
956 }
957
958 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
959 struct in6_addr router;
960 int r;
961
962 assert(link);
963 assert(link->network);
964 assert(link->manager);
965 assert(rt);
966
967 r = sd_ndisc_router_get_address(rt, &router);
968 if (r < 0)
969 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
970
971 if (in6_prefix_is_filtered(&router, 128, link->network->ndisc_allow_listed_router, link->network->ndisc_deny_listed_router)) {
972 if (DEBUG_LOGGING) {
973 if (!set_isempty(link->network->ndisc_allow_listed_router))
974 log_link_debug(link, "Router %s is not in allow list, ignoring.", IN6_ADDR_TO_STRING(&router));
975 else
976 log_link_debug(link, "Router %s is in deny list, ignoring.", IN6_ADDR_TO_STRING(&router));
977 }
978 return 0;
979 }
980
981 ndisc_mark(link, &router);
982
983 r = ndisc_start_dhcp6_client(link, rt);
984 if (r < 0)
985 return r;
986
987 r = ndisc_router_process_default(link, rt);
988 if (r < 0)
989 return r;
990
991 r = ndisc_router_process_options(link, rt);
992 if (r < 0)
993 return r;
994
995 if (link->ndisc_messages == 0) {
996 link->ndisc_configured = true;
997
998 r = ndisc_remove(link, &router);
999 if (r < 0)
1000 return r;
1001 } else
1002 log_link_debug(link, "Setting SLAAC addresses and router.");
1003
1004 if (!link->ndisc_configured)
1005 link_set_state(link, LINK_STATE_CONFIGURING);
1006
1007 link_check_ready(link);
1008 return 0;
1009 }
1010
1011 static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
1012 Link *link = ASSERT_PTR(userdata);
1013 int r;
1014
1015 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1016 return;
1017
1018 switch (event) {
1019
1020 case SD_NDISC_EVENT_ROUTER:
1021 r = ndisc_router_handler(link, rt);
1022 if (r < 0) {
1023 link_enter_failed(link);
1024 return;
1025 }
1026 break;
1027
1028 case SD_NDISC_EVENT_TIMEOUT:
1029 log_link_debug(link, "NDisc handler get timeout event");
1030 if (link->ndisc_messages == 0) {
1031 link->ndisc_configured = true;
1032 link_check_ready(link);
1033 }
1034 break;
1035 default:
1036 assert_not_reached();
1037 }
1038 }
1039
1040 static int ndisc_configure(Link *link) {
1041 int r;
1042
1043 assert(link);
1044
1045 if (!link_ipv6_accept_ra_enabled(link))
1046 return 0;
1047
1048 if (link->ndisc)
1049 return -EBUSY; /* Already configured. */
1050
1051 r = sd_ndisc_new(&link->ndisc);
1052 if (r < 0)
1053 return r;
1054
1055 r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
1056 if (r < 0)
1057 return r;
1058
1059 if (link->hw_addr.length == ETH_ALEN) {
1060 r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.ether);
1061 if (r < 0)
1062 return r;
1063 }
1064
1065 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
1066 if (r < 0)
1067 return r;
1068
1069 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
1070 if (r < 0)
1071 return r;
1072
1073 return 0;
1074 }
1075
1076 int ndisc_start(Link *link) {
1077 int r;
1078
1079 assert(link);
1080
1081 if (!link->ndisc || !link->dhcp6_client)
1082 return 0;
1083
1084 if (!link_has_carrier(link))
1085 return 0;
1086
1087 if (in6_addr_is_null(&link->ipv6ll_address))
1088 return 0;
1089
1090 log_link_debug(link, "Discovering IPv6 routers");
1091
1092 r = sd_ndisc_start(link->ndisc);
1093 if (r < 0)
1094 return r;
1095
1096 return 1;
1097 }
1098
1099 static int ndisc_process_request(Request *req, Link *link, void *userdata) {
1100 int r;
1101
1102 assert(link);
1103
1104 if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false))
1105 return 0;
1106
1107 r = ndisc_configure(link);
1108 if (r < 0)
1109 return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Discovery: %m");
1110
1111 r = ndisc_start(link);
1112 if (r < 0)
1113 return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
1114
1115 log_link_debug(link, "IPv6 Router Discovery is configured%s.",
1116 r > 0 ? " and started" : "");
1117 return 1;
1118 }
1119
1120 int link_request_ndisc(Link *link) {
1121 int r;
1122
1123 assert(link);
1124
1125 if (!link_ipv6_accept_ra_enabled(link))
1126 return 0;
1127
1128 if (link->ndisc)
1129 return 0;
1130
1131 r = link_queue_request(link, REQUEST_TYPE_NDISC, ndisc_process_request, NULL);
1132 if (r < 0)
1133 return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m");
1134
1135 log_link_debug(link, "Requested configuring of the IPv6 Router Discovery.");
1136 return 0;
1137 }
1138
1139 void ndisc_vacuum(Link *link) {
1140 NDiscRDNSS *r;
1141 NDiscDNSSL *d;
1142 usec_t now_usec;
1143
1144 assert(link);
1145 assert(link->manager);
1146
1147 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1148
1149 assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
1150
1151 SET_FOREACH(r, link->ndisc_rdnss)
1152 if (r->lifetime_usec < now_usec)
1153 free(set_remove(link->ndisc_rdnss, r));
1154
1155 SET_FOREACH(d, link->ndisc_dnssl)
1156 if (d->lifetime_usec < now_usec)
1157 free(set_remove(link->ndisc_dnssl, d));
1158 }
1159
1160 void ndisc_flush(Link *link) {
1161 assert(link);
1162
1163 /* Removes all RDNSS and DNSSL entries, without exception */
1164
1165 link->ndisc_rdnss = set_free(link->ndisc_rdnss);
1166 link->ndisc_dnssl = set_free(link->ndisc_dnssl);
1167 }
1168
1169 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1170 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1171 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1172 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1173 };
1174
1175 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);
1176
1177 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains, dhcp_use_domains, DHCPUseDomains,
1178 "Failed to parse UseDomains= setting");
1179 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
1180 "Failed to parse DHCPv6Client= setting");