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