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