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