]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
network: ndisc: add missing lifetime check
[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_prefix_get_valid_lifetime(rt, &lifetime_sec);
486 if (r < 0)
487 return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
488
489 if (lifetime_sec == 0)
490 return 0;
491
492 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &timestamp_usec);
493 if (r < 0)
494 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
495
496 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
497 if (r < 0)
498 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
499
500 r = route_new(&route);
501 if (r < 0)
502 return log_oom();
503
504 route->family = AF_INET6;
505 route->flags = RTM_F_PREFIX;
506 route->dst_prefixlen = prefixlen;
507 route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
508
509 r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
510 if (r < 0)
511 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
512
513 r = ndisc_request_route(TAKE_PTR(route), link, rt);
514 if (r < 0)
515 return log_link_error_errno(link, r, "Could not request prefix route: %m");;
516
517 return 0;
518 }
519
520 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
521 _cleanup_(route_freep) Route *route = NULL;
522 unsigned preference, prefixlen;
523 struct in6_addr gateway, dst;
524 uint32_t lifetime_sec;
525 usec_t timestamp_usec;
526 int r;
527
528 assert(link);
529
530 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime_sec);
531 if (r < 0)
532 return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m");
533
534 if (lifetime_sec == 0)
535 return 0;
536
537 r = sd_ndisc_router_route_get_address(rt, &dst);
538 if (r < 0)
539 return log_link_error_errno(link, r, "Failed to get route destination address: %m");
540
541 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
542 if (r < 0)
543 return log_link_error_errno(link, r, "Failed to get route prefix length: %m");
544
545 if (in6_prefix_is_filtered(&dst, prefixlen, link->network->ndisc_allow_listed_route_prefix, link->network->ndisc_deny_listed_route_prefix)) {
546 if (DEBUG_LOGGING) {
547 _cleanup_free_ char *buf = NULL;
548
549 (void) in6_addr_prefix_to_string(&dst, prefixlen, &buf);
550 if (!set_isempty(link->network->ndisc_allow_listed_route_prefix))
551 log_link_debug(link, "Route prefix '%s' is not in allow list, ignoring", strna(buf));
552 else
553 log_link_debug(link, "Route prefix '%s' is in deny list, ignoring", strna(buf));
554 }
555 return 0;
556 }
557
558 r = sd_ndisc_router_get_address(rt, &gateway);
559 if (r < 0)
560 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
561
562 if (link_get_ipv6_address(link, &gateway, NULL) >= 0) {
563 if (DEBUG_LOGGING) {
564 _cleanup_free_ char *buf = NULL;
565
566 (void) in6_addr_to_string(&gateway, &buf);
567 log_link_debug(link, "Advertised route gateway %s is local to the link, ignoring route", strna(buf));
568 }
569 return 0;
570 }
571
572 r = sd_ndisc_router_route_get_preference(rt, &preference);
573 if (r < 0)
574 return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
575
576 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &timestamp_usec);
577 if (r < 0)
578 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
579
580 r = route_new(&route);
581 if (r < 0)
582 return log_oom();
583
584 route->family = AF_INET6;
585 route->pref = preference;
586 route->gw.in6 = gateway;
587 route->gw_family = AF_INET6;
588 route->dst.in6 = dst;
589 route->dst_prefixlen = prefixlen;
590 route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
591
592 r = ndisc_request_route(TAKE_PTR(route), link, rt);
593 if (r < 0)
594 return log_link_error_errno(link, r, "Could not request additional route: %m");
595
596 return 0;
597 }
598
599 static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
600 siphash24_compress(&x->address, sizeof(x->address), state);
601 }
602
603 static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
604 return memcmp(&a->address, &b->address, sizeof(a->address));
605 }
606
607 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
608 ndisc_rdnss_hash_ops,
609 NDiscRDNSS,
610 ndisc_rdnss_hash_func,
611 ndisc_rdnss_compare_func,
612 free);
613
614 static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
615 uint32_t lifetime;
616 const struct in6_addr *a;
617 struct in6_addr router;
618 usec_t time_now;
619 bool updated = false;
620 int n, r;
621
622 assert(link);
623 assert(rt);
624
625 r = sd_ndisc_router_get_address(rt, &router);
626 if (r < 0)
627 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
628
629 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
630 if (r < 0)
631 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
632
633 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime);
634 if (r < 0)
635 return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
636
637 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
638 if (n < 0)
639 return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
640
641 if (lifetime == 0)
642 return 0;
643
644 if (n >= (int) NDISC_RDNSS_MAX) {
645 log_link_warning(link, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX);
646 n = NDISC_RDNSS_MAX;
647 }
648
649 for (int j = 0; j < n; j++) {
650 _cleanup_free_ NDiscRDNSS *x = NULL;
651 NDiscRDNSS *rdnss, d = {
652 .address = a[j],
653 };
654
655 rdnss = set_get(link->ndisc_rdnss, &d);
656 if (rdnss) {
657 rdnss->marked = false;
658 rdnss->router = router;
659 rdnss->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC);
660 continue;
661 }
662
663 x = new(NDiscRDNSS, 1);
664 if (!x)
665 return log_oom();
666
667 *x = (NDiscRDNSS) {
668 .address = a[j],
669 .router = router,
670 .valid_until = usec_add(time_now, lifetime * USEC_PER_SEC),
671 };
672
673 r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
674 if (r < 0)
675 return log_oom();
676 assert(r > 0);
677
678 updated = true;
679 }
680
681 if (updated)
682 link_dirty(link);
683
684 return 0;
685 }
686
687 static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
688 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x), state);
689 }
690
691 static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
692 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
693 }
694
695 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
696 ndisc_dnssl_hash_ops,
697 NDiscDNSSL,
698 ndisc_dnssl_hash_func,
699 ndisc_dnssl_compare_func,
700 free);
701
702 static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
703 _cleanup_strv_free_ char **l = NULL;
704 struct in6_addr router;
705 uint32_t lifetime;
706 usec_t time_now;
707 bool updated = false;
708 char **j;
709 int r;
710
711 assert(link);
712 assert(rt);
713
714 r = sd_ndisc_router_get_address(rt, &router);
715 if (r < 0)
716 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
717
718 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
719 if (r < 0)
720 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
721
722 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime);
723 if (r < 0)
724 return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
725
726 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
727 if (r < 0)
728 return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
729
730 if (lifetime == 0)
731 return 0;
732
733 if (strv_length(l) >= NDISC_DNSSL_MAX) {
734 log_link_warning(link, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX);
735 STRV_FOREACH(j, l + NDISC_DNSSL_MAX)
736 *j = mfree(*j);
737 }
738
739 STRV_FOREACH(j, l) {
740 _cleanup_free_ NDiscDNSSL *s = NULL;
741 NDiscDNSSL *dnssl;
742
743 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1);
744 if (!s)
745 return log_oom();
746
747 strcpy(NDISC_DNSSL_DOMAIN(s), *j);
748
749 dnssl = set_get(link->ndisc_dnssl, s);
750 if (dnssl) {
751 dnssl->marked = false;
752 dnssl->router = router;
753 dnssl->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC);
754 continue;
755 }
756
757 s->router = router;
758 s->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC);
759
760 r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
761 if (r < 0)
762 return log_oom();
763 assert(r > 0);
764
765 updated = true;
766 }
767
768 if (updated)
769 link_dirty(link);
770
771 return 0;
772 }
773
774 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
775 assert(link);
776 assert(link->network);
777 assert(rt);
778
779 for (int r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
780 uint8_t type;
781
782 if (r < 0)
783 return log_link_error_errno(link, r, "Failed to iterate through options: %m");
784 if (r == 0) /* EOF */
785 return 0;
786
787 r = sd_ndisc_router_option_get_type(rt, &type);
788 if (r < 0)
789 return log_link_error_errno(link, r, "Failed to get RA option type: %m");
790
791 switch (type) {
792
793 case SD_NDISC_OPTION_PREFIX_INFORMATION: {
794 unsigned prefixlen;
795 struct in6_addr a;
796 uint8_t flags;
797
798 r = sd_ndisc_router_prefix_get_address(rt, &a);
799 if (r < 0)
800 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
801
802 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
803 if (r < 0)
804 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
805
806 if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) {
807 if (DEBUG_LOGGING) {
808 _cleanup_free_ char *b = NULL;
809
810 (void) in6_addr_prefix_to_string(&a, prefixlen, &b);
811 if (!set_isempty(link->network->ndisc_allow_listed_prefix))
812 log_link_debug(link, "Prefix '%s' is not in allow list, ignoring", strna(b));
813 else
814 log_link_debug(link, "Prefix '%s' is in deny list, ignoring", strna(b));
815 }
816 break;
817 }
818
819 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
820 if (r < 0)
821 return log_link_error_errno(link, r, "Failed to get RA prefix flags: %m");
822
823 if (link->network->ipv6_accept_ra_use_onlink_prefix &&
824 FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) {
825 r = ndisc_router_process_onlink_prefix(link, rt);
826 if (r < 0)
827 return r;
828 }
829
830 if (link->network->ipv6_accept_ra_use_autonomous_prefix &&
831 FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) {
832 r = ndisc_router_process_autonomous_prefix(link, rt);
833 if (r < 0)
834 return r;
835 }
836 break;
837 }
838
839 case SD_NDISC_OPTION_ROUTE_INFORMATION:
840 r = ndisc_router_process_route(link, rt);
841 if (r < 0)
842 return r;
843 break;
844
845 case SD_NDISC_OPTION_RDNSS:
846 if (link->network->ipv6_accept_ra_use_dns) {
847 r = ndisc_router_process_rdnss(link, rt);
848 if (r < 0)
849 return r;
850 }
851 break;
852
853 case SD_NDISC_OPTION_DNSSL:
854 if (link->network->ipv6_accept_ra_use_dns) {
855 r = ndisc_router_process_dnssl(link, rt);
856 if (r < 0)
857 return r;
858 }
859 break;
860 }
861 }
862 }
863
864 static void ndisc_mark(Link *link, const struct in6_addr *router) {
865 NDiscRDNSS *rdnss;
866 NDiscDNSSL *dnssl;
867
868 assert(link);
869 assert(router);
870
871 link_mark_addresses(link, NETWORK_CONFIG_SOURCE_NDISC, router);
872 link_mark_routes(link, NETWORK_CONFIG_SOURCE_NDISC, router);
873
874 SET_FOREACH(rdnss, link->ndisc_rdnss)
875 if (in6_addr_equal(&rdnss->router, router))
876 rdnss->marked = true;
877
878 SET_FOREACH(dnssl, link->ndisc_dnssl)
879 if (in6_addr_equal(&dnssl->router, router))
880 dnssl->marked = true;
881 }
882
883 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
884 struct in6_addr router;
885 uint64_t flags;
886 int r;
887
888 assert(link);
889 assert(link->network);
890 assert(link->manager);
891 assert(rt);
892
893 r = sd_ndisc_router_get_address(rt, &router);
894 if (r < 0)
895 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
896
897 if (in6_prefix_is_filtered(&router, 128, link->network->ndisc_allow_listed_router, link->network->ndisc_deny_listed_router)) {
898 if (DEBUG_LOGGING) {
899 _cleanup_free_ char *buf = NULL;
900
901 (void) in6_addr_to_string(&router, &buf);
902 if (!set_isempty(link->network->ndisc_allow_listed_router))
903 log_link_debug(link, "Router '%s' is not in allow list, ignoring", strna(buf));
904 else
905 log_link_debug(link, "Router '%s' is in deny list, ignoring", strna(buf));
906 }
907 return 0;
908 }
909
910 ndisc_mark(link, &router);
911
912 r = sd_ndisc_router_get_flags(rt, &flags);
913 if (r < 0)
914 return log_link_error_errno(link, r, "Failed to get RA flags: %m");
915
916 if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER) &&
917 link->network->ipv6_accept_ra_start_dhcp6_client != IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO) ||
918 link->network->ipv6_accept_ra_start_dhcp6_client == IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS) {
919
920 if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))
921 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
922 r = dhcp6_request_information(link, !(flags & ND_RA_FLAG_MANAGED));
923 else
924 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode
925 * even if router does not have M or O flag. */
926 r = dhcp6_request_information(link, false);
927 if (r < 0 && r != -EBUSY)
928 return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
929 else
930 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
931 }
932
933 r = ndisc_router_process_default(link, rt);
934 if (r < 0)
935 return r;
936 r = ndisc_router_process_options(link, rt);
937 if (r < 0)
938 return r;
939
940 if (link->ndisc_messages == 0) {
941 link->ndisc_configured = true;
942
943 r = ndisc_remove(link, &router);
944 if (r < 0)
945 return r;
946 } else
947 log_link_debug(link, "Setting SLAAC addresses and router.");
948
949 if (!link->ndisc_configured)
950 link_set_state(link, LINK_STATE_CONFIGURING);
951
952 link_check_ready(link);
953 return 0;
954 }
955
956 static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
957 Link *link = userdata;
958 int r;
959
960 assert(link);
961
962 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
963 return;
964
965 switch (event) {
966
967 case SD_NDISC_EVENT_ROUTER:
968 r = ndisc_router_handler(link, rt);
969 if (r < 0) {
970 link_enter_failed(link);
971 return;
972 }
973 break;
974
975 case SD_NDISC_EVENT_TIMEOUT:
976 log_link_debug(link, "NDisc handler get timeout event");
977 if (link->ndisc_messages == 0) {
978 link->ndisc_configured = true;
979 link_check_ready(link);
980 }
981 break;
982 default:
983 assert_not_reached();
984 }
985 }
986
987 int ndisc_configure(Link *link) {
988 int r;
989
990 assert(link);
991
992 if (!link_ipv6_accept_ra_enabled(link))
993 return 0;
994
995 if (link->ndisc)
996 return -EBUSY; /* Already configured. */
997
998 r = sd_ndisc_new(&link->ndisc);
999 if (r < 0)
1000 return r;
1001
1002 r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
1003 if (r < 0)
1004 return r;
1005
1006 r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.ether);
1007 if (r < 0)
1008 return r;
1009
1010 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
1011 if (r < 0)
1012 return r;
1013
1014 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
1015 if (r < 0)
1016 return r;
1017
1018 return 0;
1019 }
1020
1021 int ndisc_start(Link *link) {
1022 assert(link);
1023
1024 if (!link->ndisc || !link->dhcp6_client)
1025 return 0;
1026
1027 if (!link_has_carrier(link))
1028 return 0;
1029
1030 if (in6_addr_is_null(&link->ipv6ll_address))
1031 return 0;
1032
1033 log_link_debug(link, "Discovering IPv6 routers");
1034
1035 return sd_ndisc_start(link->ndisc);
1036 }
1037
1038 void ndisc_vacuum(Link *link) {
1039 NDiscRDNSS *r;
1040 NDiscDNSSL *d;
1041 usec_t time_now;
1042
1043 assert(link);
1044
1045 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1046
1047 time_now = now(clock_boottime_or_monotonic());
1048
1049 SET_FOREACH(r, link->ndisc_rdnss)
1050 if (r->valid_until < time_now)
1051 free(set_remove(link->ndisc_rdnss, r));
1052
1053 SET_FOREACH(d, link->ndisc_dnssl)
1054 if (d->valid_until < time_now)
1055 free(set_remove(link->ndisc_dnssl, d));
1056 }
1057
1058 void ndisc_flush(Link *link) {
1059 assert(link);
1060
1061 /* Removes all RDNSS and DNSSL entries, without exception */
1062
1063 link->ndisc_rdnss = set_free(link->ndisc_rdnss);
1064 link->ndisc_dnssl = set_free(link->ndisc_dnssl);
1065 }
1066
1067 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1068 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1069 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1070 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1071 };
1072
1073 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);
1074
1075 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains, dhcp_use_domains, DHCPUseDomains,
1076 "Failed to parse UseDomains= setting");
1077 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
1078 "Failed to parse DHCPv6Client= setting");