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