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