]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
Merge pull request #24001 from yuwata/network-lifetime-fix
[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))
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 if (address_get(link, address, &existing) < 0)
282 link->ndisc_configured = false;
283 else
284 address_unmark(existing);
285
286 return link_request_address(link, TAKE_PTR(address), true, &link->ndisc_messages,
287 ndisc_address_handler, NULL);
288 }
289
290 static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
291 usec_t lifetime_usec, timestamp_usec;
292 struct in6_addr gateway;
293 uint16_t lifetime_sec;
294 unsigned preference;
295 uint32_t mtu = 0;
296 int r;
297
298 assert(link);
299 assert(link->network);
300 assert(rt);
301
302 if (!link->network->ipv6_accept_ra_use_gateway &&
303 hashmap_isempty(link->network->routes_by_section))
304 return 0;
305
306 r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec);
307 if (r < 0)
308 return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
309
310 if (lifetime_sec == 0) /* not a default router */
311 return 0;
312
313 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
314 if (r < 0)
315 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
316
317 lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec);
318
319 r = sd_ndisc_router_get_address(rt, &gateway);
320 if (r < 0)
321 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
322
323 if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
324 if (DEBUG_LOGGING)
325 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
326 IN6_ADDR_TO_STRING(&gateway));
327 return 0;
328 }
329
330 r = sd_ndisc_router_get_preference(rt, &preference);
331 if (r < 0)
332 return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
333
334 if (link->network->ipv6_accept_ra_use_mtu) {
335 r = sd_ndisc_router_get_mtu(rt, &mtu);
336 if (r < 0 && r != -ENODATA)
337 return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m");
338 }
339
340 if (link->network->ipv6_accept_ra_use_gateway) {
341 _cleanup_(route_freep) Route *route = NULL;
342
343 r = route_new(&route);
344 if (r < 0)
345 return log_oom();
346
347 route->family = AF_INET6;
348 route->pref = preference;
349 route->gw_family = AF_INET6;
350 route->gw.in6 = gateway;
351 route->lifetime_usec = lifetime_usec;
352 route->mtu = mtu;
353
354 r = ndisc_request_route(TAKE_PTR(route), link, rt);
355 if (r < 0)
356 return log_link_error_errno(link, r, "Could not request default route: %m");
357 }
358
359 Route *route_gw;
360 HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
361 _cleanup_(route_freep) Route *route = NULL;
362
363 if (!route_gw->gateway_from_dhcp_or_ra)
364 continue;
365
366 if (route_gw->gw_family != AF_INET6)
367 continue;
368
369 r = route_dup(route_gw, &route);
370 if (r < 0)
371 return r;
372
373 route->gw.in6 = gateway;
374 if (!route->pref_set)
375 route->pref = preference;
376 route->lifetime_usec = lifetime_usec;
377 if (route->mtu == 0)
378 route->mtu = mtu;
379
380 r = ndisc_request_route(TAKE_PTR(route), link, rt);
381 if (r < 0)
382 return log_link_error_errno(link, r, "Could not request gateway: %m");
383 }
384
385 return 0;
386 }
387
388 static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
389 uint32_t lifetime_valid_sec, lifetime_preferred_sec;
390 usec_t lifetime_valid_usec, lifetime_preferred_usec, timestamp_usec;
391 _cleanup_set_free_ Set *addresses = NULL;
392 struct in6_addr prefix, *a;
393 unsigned prefixlen;
394 int r;
395
396 assert(link);
397 assert(link->network);
398 assert(rt);
399
400 if (!link->network->ipv6_accept_ra_use_autonomous_prefix)
401 return 0;
402
403 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
404 if (r < 0)
405 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
406
407 r = sd_ndisc_router_prefix_get_address(rt, &prefix);
408 if (r < 0)
409 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
410
411 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
412 if (r < 0)
413 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
414
415 /* ndisc_generate_addresses() below requires the prefix length <= 64. */
416 if (prefixlen > 64) {
417 log_link_debug(link, "Prefix is longer than 64, ignoring autonomous prefix %s.",
418 IN6_ADDR_PREFIX_TO_STRING(&prefix, prefixlen));
419 return 0;
420 }
421
422 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid_sec);
423 if (r < 0)
424 return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
425
426 if (lifetime_valid_sec == 0) {
427 log_link_debug(link, "Ignoring prefix as its valid lifetime is zero.");
428 return 0;
429 }
430
431 r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred_sec);
432 if (r < 0)
433 return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
434
435 /* The preferred lifetime is never greater than the valid lifetime */
436 if (lifetime_preferred_sec > lifetime_valid_sec)
437 return 0;
438
439 lifetime_valid_usec = sec_to_usec(lifetime_valid_sec, timestamp_usec);
440 lifetime_preferred_usec = sec_to_usec(lifetime_preferred_sec, timestamp_usec);
441
442 r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses);
443 if (r < 0)
444 return log_link_error_errno(link, r, "Failed to generate SLAAC addresses: %m");
445
446 SET_FOREACH(a, addresses) {
447 _cleanup_(address_freep) Address *address = NULL;
448 Address *e;
449
450 r = address_new(&address);
451 if (r < 0)
452 return log_oom();
453
454 address->family = AF_INET6;
455 address->in_addr.in6 = *a;
456 address->prefixlen = prefixlen;
457 address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
458 address->lifetime_valid_usec = lifetime_valid_usec;
459 address->lifetime_preferred_usec = lifetime_preferred_usec;
460
461 /* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by
462 * honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events.
463 * See draft-ietf-6man-slaac-renum-02, section 4.2. */
464 r = address_get(link, address, &e);
465 if (r > 0) {
466 /* If the address is already assigned, but not valid anymore, then refuse to
467 * update the address, and it will be removed. */
468 if (e->lifetime_valid_usec < timestamp_usec)
469 continue;
470 }
471
472 r = ndisc_request_address(TAKE_PTR(address), link, rt);
473 if (r < 0)
474 return log_link_error_errno(link, r, "Could not request SLAAC address: %m");
475 }
476
477 return 0;
478 }
479
480 static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
481 _cleanup_(route_freep) Route *route = NULL;
482 usec_t timestamp_usec;
483 uint32_t lifetime_sec;
484 unsigned prefixlen;
485 int r;
486
487 assert(link);
488 assert(link->network);
489 assert(rt);
490
491 if (!link->network->ipv6_accept_ra_use_onlink_prefix)
492 return 0;
493
494 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec);
495 if (r < 0)
496 return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
497
498 if (lifetime_sec == 0)
499 return 0;
500
501 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
502 if (r < 0)
503 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
504
505 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
506 if (r < 0)
507 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
508
509 r = route_new(&route);
510 if (r < 0)
511 return log_oom();
512
513 route->family = AF_INET6;
514 route->flags = RTM_F_PREFIX;
515 route->dst_prefixlen = prefixlen;
516 route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
517
518 r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
519 if (r < 0)
520 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
521
522 r = ndisc_request_route(TAKE_PTR(route), link, rt);
523 if (r < 0)
524 return log_link_error_errno(link, r, "Could not request prefix route: %m");
525
526 return 0;
527 }
528
529 static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) {
530 unsigned prefixlen;
531 struct in6_addr a;
532 uint8_t flags;
533 int r;
534
535 assert(link);
536 assert(link->network);
537 assert(rt);
538
539 r = sd_ndisc_router_prefix_get_address(rt, &a);
540 if (r < 0)
541 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
542
543 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
544 if (r < 0)
545 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
546
547 if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) {
548 if (DEBUG_LOGGING)
549 log_link_debug(link, "Prefix '%s' is %s, ignoring",
550 !set_isempty(link->network->ndisc_allow_listed_prefix) ? "not in allow list"
551 : "in deny list",
552 IN6_ADDR_PREFIX_TO_STRING(&a, prefixlen));
553 return 0;
554 }
555
556 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
557 if (r < 0)
558 return log_link_error_errno(link, r, "Failed to get RA prefix flags: %m");
559
560 if (FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) {
561 r = ndisc_router_process_onlink_prefix(link, rt);
562 if (r < 0)
563 return r;
564 }
565
566 if (FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) {
567 r = ndisc_router_process_autonomous_prefix(link, rt);
568 if (r < 0)
569 return r;
570 }
571
572 return 0;
573 }
574
575 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
576 _cleanup_(route_freep) Route *route = NULL;
577 unsigned preference, prefixlen;
578 struct in6_addr gateway, dst;
579 uint32_t lifetime_sec;
580 usec_t timestamp_usec;
581 int r;
582
583 assert(link);
584
585 if (!link->network->ipv6_accept_ra_use_route_prefix)
586 return 0;
587
588 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime_sec);
589 if (r < 0)
590 return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m");
591
592 if (lifetime_sec == 0)
593 return 0;
594
595 r = sd_ndisc_router_route_get_address(rt, &dst);
596 if (r < 0)
597 return log_link_error_errno(link, r, "Failed to get route destination address: %m");
598
599 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
600 if (r < 0)
601 return log_link_error_errno(link, r, "Failed to get route prefix length: %m");
602
603 if (in6_addr_is_null(&dst) && prefixlen == 0) {
604 log_link_debug(link, "Route prefix is ::/0, ignoring");
605 return 0;
606 }
607
608 if (in6_prefix_is_filtered(&dst, prefixlen,
609 link->network->ndisc_allow_listed_route_prefix,
610 link->network->ndisc_deny_listed_route_prefix)) {
611
612 if (DEBUG_LOGGING)
613 log_link_debug(link, "Route prefix %s is %s, ignoring",
614 !set_isempty(link->network->ndisc_allow_listed_route_prefix) ? "not in allow list"
615 : "in deny list",
616 IN6_ADDR_PREFIX_TO_STRING(&dst, prefixlen));
617 return 0;
618 }
619
620 r = sd_ndisc_router_get_address(rt, &gateway);
621 if (r < 0)
622 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
623
624 if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
625 if (DEBUG_LOGGING)
626 log_link_debug(link, "Advertised route gateway %s is local to the link, ignoring route",
627 IN6_ADDR_TO_STRING(&gateway));
628 return 0;
629 }
630
631 r = sd_ndisc_router_route_get_preference(rt, &preference);
632 if (r < 0)
633 return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
634
635 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
636 if (r < 0)
637 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
638
639 r = route_new(&route);
640 if (r < 0)
641 return log_oom();
642
643 route->family = AF_INET6;
644 route->pref = preference;
645 route->gw.in6 = gateway;
646 route->gw_family = AF_INET6;
647 route->dst.in6 = dst;
648 route->dst_prefixlen = prefixlen;
649 route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
650
651 r = ndisc_request_route(TAKE_PTR(route), link, rt);
652 if (r < 0)
653 return log_link_error_errno(link, r, "Could not request additional route: %m");
654
655 return 0;
656 }
657
658 static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
659 siphash24_compress(&x->address, sizeof(x->address), state);
660 }
661
662 static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
663 return memcmp(&a->address, &b->address, sizeof(a->address));
664 }
665
666 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
667 ndisc_rdnss_hash_ops,
668 NDiscRDNSS,
669 ndisc_rdnss_hash_func,
670 ndisc_rdnss_compare_func,
671 free);
672
673 static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
674 usec_t lifetime_usec, timestamp_usec;
675 uint32_t lifetime_sec;
676 const struct in6_addr *a;
677 struct in6_addr router;
678 bool updated = false;
679 int n, r;
680
681 assert(link);
682 assert(link->network);
683 assert(rt);
684
685 if (!link->network->ipv6_accept_ra_use_dns)
686 return 0;
687
688 r = sd_ndisc_router_get_address(rt, &router);
689 if (r < 0)
690 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
691
692 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
693 if (r < 0)
694 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
695
696 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime_sec);
697 if (r < 0)
698 return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
699
700 if (lifetime_sec == 0)
701 return 0;
702
703 lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
704
705 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
706 if (n < 0)
707 return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
708
709 if (n >= (int) NDISC_RDNSS_MAX) {
710 log_link_warning(link, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX);
711 n = NDISC_RDNSS_MAX;
712 }
713
714 for (int j = 0; j < n; j++) {
715 _cleanup_free_ NDiscRDNSS *x = NULL;
716 NDiscRDNSS *rdnss, d = {
717 .address = a[j],
718 };
719
720 rdnss = set_get(link->ndisc_rdnss, &d);
721 if (rdnss) {
722 rdnss->marked = false;
723 rdnss->router = router;
724 rdnss->lifetime_usec = lifetime_usec;
725 continue;
726 }
727
728 x = new(NDiscRDNSS, 1);
729 if (!x)
730 return log_oom();
731
732 *x = (NDiscRDNSS) {
733 .address = a[j],
734 .router = router,
735 .lifetime_usec = lifetime_usec,
736 };
737
738 r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
739 if (r < 0)
740 return log_oom();
741 assert(r > 0);
742
743 updated = true;
744 }
745
746 if (updated)
747 link_dirty(link);
748
749 return 0;
750 }
751
752 static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
753 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x), state);
754 }
755
756 static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
757 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
758 }
759
760 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
761 ndisc_dnssl_hash_ops,
762 NDiscDNSSL,
763 ndisc_dnssl_hash_func,
764 ndisc_dnssl_compare_func,
765 free);
766
767 static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
768 _cleanup_strv_free_ char **l = NULL;
769 usec_t lifetime_usec, timestamp_usec;
770 struct in6_addr router;
771 uint32_t lifetime_sec;
772 bool updated = false;
773 int r;
774
775 assert(link);
776 assert(link->network);
777 assert(rt);
778
779 if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_NO)
780 return 0;
781
782 r = sd_ndisc_router_get_address(rt, &router);
783 if (r < 0)
784 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
785
786 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
787 if (r < 0)
788 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
789
790 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime_sec);
791 if (r < 0)
792 return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
793
794 if (lifetime_sec == 0)
795 return 0;
796
797 lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
798
799 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
800 if (r < 0)
801 return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
802
803 if (strv_length(l) >= NDISC_DNSSL_MAX) {
804 log_link_warning(link, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX);
805 STRV_FOREACH(j, l + NDISC_DNSSL_MAX)
806 *j = mfree(*j);
807 }
808
809 STRV_FOREACH(j, l) {
810 _cleanup_free_ NDiscDNSSL *s = NULL;
811 NDiscDNSSL *dnssl;
812
813 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1);
814 if (!s)
815 return log_oom();
816
817 strcpy(NDISC_DNSSL_DOMAIN(s), *j);
818
819 dnssl = set_get(link->ndisc_dnssl, s);
820 if (dnssl) {
821 dnssl->marked = false;
822 dnssl->router = router;
823 dnssl->lifetime_usec = lifetime_usec;
824 continue;
825 }
826
827 s->router = router;
828 s->lifetime_usec = lifetime_usec;
829
830 r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
831 if (r < 0)
832 return log_oom();
833 assert(r > 0);
834
835 updated = true;
836 }
837
838 if (updated)
839 link_dirty(link);
840
841 return 0;
842 }
843
844 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
845 int r;
846
847 assert(link);
848 assert(link->network);
849 assert(rt);
850
851 for (r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
852 uint8_t type;
853
854 if (r < 0)
855 return log_link_error_errno(link, r, "Failed to iterate through options: %m");
856 if (r == 0) /* EOF */
857 return 0;
858
859 r = sd_ndisc_router_option_get_type(rt, &type);
860 if (r < 0)
861 return log_link_error_errno(link, r, "Failed to get RA option type: %m");
862
863 switch (type) {
864
865 case SD_NDISC_OPTION_PREFIX_INFORMATION:
866 r = ndisc_router_process_prefix(link, rt);
867 if (r < 0)
868 return r;
869 break;
870
871 case SD_NDISC_OPTION_ROUTE_INFORMATION:
872 r = ndisc_router_process_route(link, rt);
873 if (r < 0)
874 return r;
875 break;
876
877 case SD_NDISC_OPTION_RDNSS:
878 r = ndisc_router_process_rdnss(link, rt);
879 if (r < 0)
880 return r;
881 break;
882
883 case SD_NDISC_OPTION_DNSSL:
884 r = ndisc_router_process_dnssl(link, rt);
885 if (r < 0)
886 return r;
887 break;
888 }
889 }
890 }
891
892 static void ndisc_mark(Link *link, const struct in6_addr *router) {
893 NDiscRDNSS *rdnss;
894 NDiscDNSSL *dnssl;
895
896 assert(link);
897 assert(router);
898
899 link_mark_addresses(link, NETWORK_CONFIG_SOURCE_NDISC, router);
900 link_mark_routes(link, NETWORK_CONFIG_SOURCE_NDISC, router);
901
902 SET_FOREACH(rdnss, link->ndisc_rdnss)
903 if (in6_addr_equal(&rdnss->router, router))
904 rdnss->marked = true;
905
906 SET_FOREACH(dnssl, link->ndisc_dnssl)
907 if (in6_addr_equal(&dnssl->router, router))
908 dnssl->marked = true;
909 }
910
911 static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) {
912 int r;
913
914 assert(link);
915 assert(link->network);
916
917 switch (link->network->ipv6_accept_ra_start_dhcp6_client) {
918 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO:
919 return 0;
920
921 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES: {
922 uint64_t flags;
923
924 r = sd_ndisc_router_get_flags(rt, &flags);
925 if (r < 0)
926 return log_link_warning_errno(link, r, "Failed to get RA flags: %m");
927
928 if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) == 0)
929 return 0;
930
931 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags.
932 * Note, if both "managed" and "other configuration" bits are set, then ignore
933 * "other configuration" bit. See RFC 4861. */
934 r = dhcp6_start_on_ra(link, !(flags & ND_RA_FLAG_MANAGED));
935 break;
936 }
937 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS:
938 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in solicit mode
939 * even if the router flags have neither M nor O flags. */
940 r = dhcp6_start_on_ra(link, /* information_request = */ false);
941 break;
942
943 default:
944 assert_not_reached();
945 }
946
947 if (r < 0)
948 return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
949
950 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
951 return 0;
952 }
953
954 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
955 struct in6_addr router;
956 int r;
957
958 assert(link);
959 assert(link->network);
960 assert(link->manager);
961 assert(rt);
962
963 r = sd_ndisc_router_get_address(rt, &router);
964 if (r < 0)
965 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
966
967 if (in6_prefix_is_filtered(&router, 128, link->network->ndisc_allow_listed_router, link->network->ndisc_deny_listed_router)) {
968 if (DEBUG_LOGGING) {
969 if (!set_isempty(link->network->ndisc_allow_listed_router))
970 log_link_debug(link, "Router %s is not in allow list, ignoring.", IN6_ADDR_TO_STRING(&router));
971 else
972 log_link_debug(link, "Router %s is in deny list, ignoring.", IN6_ADDR_TO_STRING(&router));
973 }
974 return 0;
975 }
976
977 ndisc_mark(link, &router);
978
979 r = ndisc_start_dhcp6_client(link, rt);
980 if (r < 0)
981 return r;
982
983 r = ndisc_router_process_default(link, rt);
984 if (r < 0)
985 return r;
986
987 r = ndisc_router_process_options(link, rt);
988 if (r < 0)
989 return r;
990
991 if (link->ndisc_messages == 0) {
992 link->ndisc_configured = true;
993
994 r = ndisc_remove(link, &router);
995 if (r < 0)
996 return r;
997 } else
998 log_link_debug(link, "Setting SLAAC addresses and router.");
999
1000 if (!link->ndisc_configured)
1001 link_set_state(link, LINK_STATE_CONFIGURING);
1002
1003 link_check_ready(link);
1004 return 0;
1005 }
1006
1007 static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
1008 Link *link = userdata;
1009 int r;
1010
1011 assert(link);
1012
1013 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1014 return;
1015
1016 switch (event) {
1017
1018 case SD_NDISC_EVENT_ROUTER:
1019 r = ndisc_router_handler(link, rt);
1020 if (r < 0) {
1021 link_enter_failed(link);
1022 return;
1023 }
1024 break;
1025
1026 case SD_NDISC_EVENT_TIMEOUT:
1027 log_link_debug(link, "NDisc handler get timeout event");
1028 if (link->ndisc_messages == 0) {
1029 link->ndisc_configured = true;
1030 link_check_ready(link);
1031 }
1032 break;
1033 default:
1034 assert_not_reached();
1035 }
1036 }
1037
1038 static int ndisc_configure(Link *link) {
1039 int r;
1040
1041 assert(link);
1042
1043 if (!link_ipv6_accept_ra_enabled(link))
1044 return 0;
1045
1046 if (link->ndisc)
1047 return -EBUSY; /* Already configured. */
1048
1049 r = sd_ndisc_new(&link->ndisc);
1050 if (r < 0)
1051 return r;
1052
1053 r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
1054 if (r < 0)
1055 return r;
1056
1057 if (link->hw_addr.length == ETH_ALEN) {
1058 r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.ether);
1059 if (r < 0)
1060 return r;
1061 }
1062
1063 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
1064 if (r < 0)
1065 return r;
1066
1067 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
1068 if (r < 0)
1069 return r;
1070
1071 return 0;
1072 }
1073
1074 int ndisc_start(Link *link) {
1075 int r;
1076
1077 assert(link);
1078
1079 if (!link->ndisc || !link->dhcp6_client)
1080 return 0;
1081
1082 if (!link_has_carrier(link))
1083 return 0;
1084
1085 if (in6_addr_is_null(&link->ipv6ll_address))
1086 return 0;
1087
1088 log_link_debug(link, "Discovering IPv6 routers");
1089
1090 r = sd_ndisc_start(link->ndisc);
1091 if (r < 0)
1092 return r;
1093
1094 return 1;
1095 }
1096
1097 static int ndisc_process_request(Request *req, Link *link, void *userdata) {
1098 int r;
1099
1100 assert(link);
1101
1102 if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
1103 return 0;
1104
1105 r = ndisc_configure(link);
1106 if (r < 0)
1107 return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Discovery: %m");
1108
1109 r = ndisc_start(link);
1110 if (r < 0)
1111 return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
1112
1113 log_link_debug(link, "IPv6 Router Discovery is configured%s.",
1114 r > 0 ? " and started" : "");
1115 return 1;
1116 }
1117
1118 int link_request_ndisc(Link *link) {
1119 int r;
1120
1121 assert(link);
1122
1123 if (!link_ipv6_accept_ra_enabled(link))
1124 return 0;
1125
1126 if (link->ndisc)
1127 return 0;
1128
1129 r = link_queue_request(link, REQUEST_TYPE_NDISC, ndisc_process_request, NULL);
1130 if (r < 0)
1131 return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m");
1132
1133 log_link_debug(link, "Requested configuring of the IPv6 Router Discovery.");
1134 return 0;
1135 }
1136
1137 void ndisc_vacuum(Link *link) {
1138 NDiscRDNSS *r;
1139 NDiscDNSSL *d;
1140 usec_t now_usec;
1141
1142 assert(link);
1143 assert(link->manager);
1144
1145 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1146
1147 assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
1148
1149 SET_FOREACH(r, link->ndisc_rdnss)
1150 if (r->lifetime_usec < now_usec)
1151 free(set_remove(link->ndisc_rdnss, r));
1152
1153 SET_FOREACH(d, link->ndisc_dnssl)
1154 if (d->lifetime_usec < now_usec)
1155 free(set_remove(link->ndisc_dnssl, d));
1156 }
1157
1158 void ndisc_flush(Link *link) {
1159 assert(link);
1160
1161 /* Removes all RDNSS and DNSSL entries, without exception */
1162
1163 link->ndisc_rdnss = set_free(link->ndisc_rdnss);
1164 link->ndisc_dnssl = set_free(link->ndisc_dnssl);
1165 }
1166
1167 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1168 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1169 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1170 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1171 };
1172
1173 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);
1174
1175 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains, dhcp_use_domains, DHCPUseDomains,
1176 "Failed to parse UseDomains= setting");
1177 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
1178 "Failed to parse DHCPv6Client= setting");