]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
e8606506916e0697c535aca80b66bd546b2993ae
[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 "event-util.h"
14 #include "missing_network.h"
15 #include "networkd-address-generation.h"
16 #include "networkd-address.h"
17 #include "networkd-dhcp6.h"
18 #include "networkd-manager.h"
19 #include "networkd-ndisc.h"
20 #include "networkd-queue.h"
21 #include "networkd-route.h"
22 #include "networkd-state-file.h"
23 #include "string-table.h"
24 #include "string-util.h"
25 #include "strv.h"
26 #include "sysctl-util.h"
27
28 #define NDISC_DNSSL_MAX 64U
29 #define NDISC_RDNSS_MAX 64U
30 /* Not defined RFC, but let's set an upper limit to make not consume much memory.
31 * This should be safe as typically there should be at most 1 portal per network. */
32 #define NDISC_CAPTIVE_PORTAL_MAX 64U
33
34 bool link_ipv6_accept_ra_enabled(Link *link) {
35 assert(link);
36
37 if (!socket_ipv6_is_supported())
38 return false;
39
40 if (link->flags & IFF_LOOPBACK)
41 return false;
42
43 if (link->iftype == ARPHRD_CAN)
44 return false;
45
46 if (!link->network)
47 return false;
48
49 if (!link_may_have_ipv6ll(link, /* check_multicast = */ true))
50 return false;
51
52 assert(link->network->ipv6_accept_ra >= 0);
53 return link->network->ipv6_accept_ra;
54 }
55
56 void network_adjust_ipv6_accept_ra(Network *network) {
57 assert(network);
58
59 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
60 if (network->ipv6_accept_ra > 0)
61 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link-local addressing is disabled or not supported. "
62 "Disabling IPv6AcceptRA=.", network->filename);
63 network->ipv6_accept_ra = false;
64 }
65
66 if (network->ipv6_accept_ra < 0)
67 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
68 network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6);
69
70 /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
71 * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
72 if (!set_isempty(network->ndisc_allow_listed_router))
73 network->ndisc_deny_listed_router = set_free_free(network->ndisc_deny_listed_router);
74 if (!set_isempty(network->ndisc_allow_listed_prefix))
75 network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix);
76 if (!set_isempty(network->ndisc_allow_listed_route_prefix))
77 network->ndisc_deny_listed_route_prefix = set_free_free(network->ndisc_deny_listed_route_prefix);
78 }
79
80 static int ndisc_check_ready(Link *link);
81
82 static int ndisc_address_ready_callback(Address *address) {
83 Address *a;
84
85 assert(address);
86 assert(address->link);
87
88 SET_FOREACH(a, address->link->addresses)
89 if (a->source == NETWORK_CONFIG_SOURCE_NDISC)
90 a->callback = NULL;
91
92 return ndisc_check_ready(address->link);
93 }
94
95 static int ndisc_check_ready(Link *link) {
96 bool found = false, ready = false;
97 Address *address;
98
99 assert(link);
100
101 if (link->ndisc_messages > 0) {
102 log_link_debug(link, "%s(): SLAAC addresses and routes are not set.", __func__);
103 return 0;
104 }
105
106 SET_FOREACH(address, link->addresses) {
107 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
108 continue;
109
110 found = true;
111
112 if (address_is_ready(address)) {
113 ready = true;
114 break;
115 }
116 }
117
118 if (found && !ready) {
119 SET_FOREACH(address, link->addresses)
120 if (address->source == NETWORK_CONFIG_SOURCE_NDISC)
121 address->callback = ndisc_address_ready_callback;
122
123 log_link_debug(link, "%s(): no SLAAC address is ready.", __func__);
124 return 0;
125 }
126
127 link->ndisc_configured = true;
128 log_link_debug(link, "SLAAC addresses and routes set.");
129
130 link_check_ready(link);
131 return 0;
132 }
133
134 static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
135 int r;
136
137 assert(link);
138
139 r = route_configure_handler_internal(rtnl, m, link, "Could not set NDisc route");
140 if (r <= 0)
141 return r;
142
143 r = ndisc_check_ready(link);
144 if (r < 0)
145 link_enter_failed(link);
146
147 return 1;
148 }
149
150 static void ndisc_set_route_priority(Link *link, Route *route) {
151 assert(link);
152 assert(route);
153
154 if (route->priority_set)
155 return; /* explicitly configured. */
156
157 switch (route->pref) {
158 case SD_NDISC_PREFERENCE_LOW:
159 route->priority = link->network->ipv6_accept_ra_route_metric_low;
160 break;
161 case SD_NDISC_PREFERENCE_MEDIUM:
162 route->priority = link->network->ipv6_accept_ra_route_metric_medium;
163 break;
164 case SD_NDISC_PREFERENCE_HIGH:
165 route->priority = link->network->ipv6_accept_ra_route_metric_high;
166 break;
167 default:
168 assert_not_reached();
169 }
170 }
171
172 static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
173 _cleanup_(route_freep) Route *route = in;
174 struct in6_addr router;
175 uint8_t hop_limit = 0;
176 uint32_t mtu = 0;
177 bool is_new;
178 int r;
179
180 assert(route);
181 assert(link);
182 assert(link->network);
183 assert(rt);
184
185 r = sd_ndisc_router_get_address(rt, &router);
186 if (r < 0)
187 return r;
188
189 if (link->network->ipv6_accept_ra_use_mtu) {
190 r = sd_ndisc_router_get_mtu(rt, &mtu);
191 if (r < 0 && r != -ENODATA)
192 return log_link_warning_errno(link, r, "Failed to get default router MTU from RA: %m");
193 }
194
195 if (link->network->ipv6_accept_ra_use_hop_limit) {
196 r = sd_ndisc_router_get_hop_limit(rt, &hop_limit);
197 if (r < 0 && r != -ENODATA)
198 return log_link_warning_errno(link, r, "Failed to get default router hop limit from RA: %m");
199 }
200
201 route->source = NETWORK_CONFIG_SOURCE_NDISC;
202 route->provider.in6 = router;
203 if (!route->table_set)
204 route->table = link_get_ipv6_accept_ra_route_table(link);
205 ndisc_set_route_priority(link, route);
206 if (!route->protocol_set)
207 route->protocol = RTPROT_RA;
208 if (route->quickack < 0)
209 route->quickack = link->network->ipv6_accept_ra_quickack;
210 if (route->mtu == 0)
211 route->mtu = mtu;
212
213 if (route->hop_limit == 0)
214 route->hop_limit = hop_limit;
215
216 is_new = route_get(NULL, link, route, NULL) < 0;
217
218 r = link_request_route(link, TAKE_PTR(route), true, &link->ndisc_messages,
219 ndisc_route_handler, NULL);
220 if (r < 0)
221 return r;
222 if (r > 0 && is_new)
223 link->ndisc_configured = false;
224
225 return 0;
226 }
227
228 static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
229 int r;
230
231 assert(link);
232
233 r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address");
234 if (r <= 0)
235 return r;
236
237 r = ndisc_check_ready(link);
238 if (r < 0)
239 link_enter_failed(link);
240
241 return 1;
242 }
243
244 static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {
245 _cleanup_(address_freep) Address *address = in;
246 struct in6_addr router;
247 bool is_new;
248 int r;
249
250 assert(address);
251 assert(link);
252 assert(rt);
253
254 r = sd_ndisc_router_get_address(rt, &router);
255 if (r < 0)
256 return r;
257
258 address->source = NETWORK_CONFIG_SOURCE_NDISC;
259 address->provider.in6 = router;
260
261 r = free_and_strdup_warn(&address->netlabel, link->network->ndisc_netlabel);
262 if (r < 0)
263 return r;
264
265 is_new = address_get(link, address, NULL) < 0;
266
267 r = link_request_address(link, address, &link->ndisc_messages,
268 ndisc_address_handler, NULL);
269 if (r < 0)
270 return r;
271 if (r > 0 && is_new)
272 link->ndisc_configured = false;
273
274 return 0;
275 }
276
277 static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
278 usec_t lifetime_usec, timestamp_usec;
279 uint32_t icmp6_ratelimit = 0;
280 struct in6_addr gateway;
281 uint16_t lifetime_sec;
282 unsigned preference;
283 int r;
284
285 assert(link);
286 assert(link->network);
287 assert(rt);
288
289 if (!link->network->ipv6_accept_ra_use_gateway &&
290 hashmap_isempty(link->network->routes_by_section))
291 return 0;
292
293 r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec);
294 if (r < 0)
295 return log_link_warning_errno(link, r, "Failed to get gateway lifetime from RA: %m");
296
297 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
298 if (r < 0)
299 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
300
301 lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec);
302
303 r = sd_ndisc_router_get_address(rt, &gateway);
304 if (r < 0)
305 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
306
307 if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
308 if (DEBUG_LOGGING)
309 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
310 IN6_ADDR_TO_STRING(&gateway));
311 return 0;
312 }
313
314 r = sd_ndisc_router_get_preference(rt, &preference);
315 if (r < 0)
316 return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
317
318 if (link->network->ipv6_accept_ra_use_gateway) {
319 _cleanup_(route_freep) Route *route = NULL;
320
321 r = route_new(&route);
322 if (r < 0)
323 return log_oom();
324
325 route->family = AF_INET6;
326 route->pref = preference;
327 route->gw_family = AF_INET6;
328 route->gw.in6 = gateway;
329 route->lifetime_usec = lifetime_usec;
330
331 r = ndisc_request_route(TAKE_PTR(route), link, rt);
332 if (r < 0)
333 return log_link_warning_errno(link, r, "Could not request default route: %m");
334 }
335
336 Route *route_gw;
337 HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
338 _cleanup_(route_freep) Route *route = NULL;
339
340 if (!route_gw->gateway_from_dhcp_or_ra)
341 continue;
342
343 if (route_gw->gw_family != AF_INET6)
344 continue;
345
346 r = route_dup(route_gw, &route);
347 if (r < 0)
348 return r;
349
350 route->gw.in6 = gateway;
351 if (!route->pref_set)
352 route->pref = preference;
353 route->lifetime_usec = lifetime_usec;
354
355 r = ndisc_request_route(TAKE_PTR(route), link, rt);
356 if (r < 0)
357 return log_link_warning_errno(link, r, "Could not request gateway: %m");
358 }
359
360 r = sd_ndisc_router_get_icmp6_ratelimit(rt, &icmp6_ratelimit);
361 if (r < 0)
362 log_link_debug(link, "Failed to get default router preference from RA: %m");
363
364 if (icmp6_ratelimit > 0 && link->network->ipv6_accept_ra_use_icmp6_ratelimit) {
365 char buf[DECIMAL_STR_MAX(unsigned)];
366
367 xsprintf(buf, "%u", icmp6_ratelimit);
368
369 r = sysctl_write("net/ipv6/icmp/ratelimit", buf);
370 if (r < 0)
371 log_link_warning_errno(link, r, "Could not configure icmp6 rate limit: %m");
372 }
373
374 return 0;
375 }
376
377 static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
378 uint32_t lifetime_valid_sec, lifetime_preferred_sec;
379 usec_t lifetime_valid_usec, lifetime_preferred_usec, timestamp_usec;
380 _cleanup_set_free_ Set *addresses = NULL;
381 struct in6_addr prefix, *a;
382 unsigned prefixlen;
383 int r;
384
385 assert(link);
386 assert(link->network);
387 assert(rt);
388
389 if (!link->network->ipv6_accept_ra_use_autonomous_prefix)
390 return 0;
391
392 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
393 if (r < 0)
394 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
395
396 r = sd_ndisc_router_prefix_get_address(rt, &prefix);
397 if (r < 0)
398 return log_link_warning_errno(link, r, "Failed to get prefix address: %m");
399
400 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
401 if (r < 0)
402 return log_link_warning_errno(link, r, "Failed to get prefix length: %m");
403
404 /* ndisc_generate_addresses() below requires the prefix length <= 64. */
405 if (prefixlen > 64) {
406 log_link_debug(link, "Prefix is longer than 64, ignoring autonomous prefix %s.",
407 IN6_ADDR_PREFIX_TO_STRING(&prefix, prefixlen));
408 return 0;
409 }
410
411 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid_sec);
412 if (r < 0)
413 return log_link_warning_errno(link, r, "Failed to get prefix valid lifetime: %m");
414
415 r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred_sec);
416 if (r < 0)
417 return log_link_warning_errno(link, r, "Failed to get prefix preferred lifetime: %m");
418
419 /* The preferred lifetime is never greater than the valid lifetime */
420 if (lifetime_preferred_sec > lifetime_valid_sec)
421 return 0;
422
423 lifetime_valid_usec = sec_to_usec(lifetime_valid_sec, timestamp_usec);
424 lifetime_preferred_usec = sec_to_usec(lifetime_preferred_sec, timestamp_usec);
425
426 r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses);
427 if (r < 0)
428 return log_link_warning_errno(link, r, "Failed to generate SLAAC addresses: %m");
429
430 SET_FOREACH(a, addresses) {
431 _cleanup_(address_freep) Address *address = NULL;
432
433 r = address_new(&address);
434 if (r < 0)
435 return log_oom();
436
437 address->family = AF_INET6;
438 address->in_addr.in6 = *a;
439 address->prefixlen = prefixlen;
440 address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
441 address->lifetime_valid_usec = lifetime_valid_usec;
442 address->lifetime_preferred_usec = lifetime_preferred_usec;
443
444 r = ndisc_request_address(TAKE_PTR(address), link, rt);
445 if (r < 0)
446 return log_link_warning_errno(link, r, "Could not request SLAAC address: %m");
447 }
448
449 return 0;
450 }
451
452 static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
453 _cleanup_(route_freep) Route *route = NULL;
454 unsigned prefixlen, preference;
455 usec_t timestamp_usec;
456 uint32_t lifetime_sec;
457 struct in6_addr prefix;
458 int r;
459
460 assert(link);
461 assert(link->network);
462 assert(rt);
463
464 if (!link->network->ipv6_accept_ra_use_onlink_prefix)
465 return 0;
466
467 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec);
468 if (r < 0)
469 return log_link_warning_errno(link, r, "Failed to get prefix lifetime: %m");
470
471 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
472 if (r < 0)
473 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
474
475 r = sd_ndisc_router_prefix_get_address(rt, &prefix);
476 if (r < 0)
477 return log_link_warning_errno(link, r, "Failed to get prefix address: %m");
478
479 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
480 if (r < 0)
481 return log_link_warning_errno(link, r, "Failed to get prefix length: %m");
482
483 /* Prefix Information option does not have preference, hence we use the 'main' preference here */
484 r = sd_ndisc_router_get_preference(rt, &preference);
485 if (r < 0)
486 log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
487
488 r = route_new(&route);
489 if (r < 0)
490 return log_oom();
491
492 route->family = AF_INET6;
493 route->dst.in6 = prefix;
494 route->dst_prefixlen = prefixlen;
495 route->pref = preference;
496 route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
497
498 r = ndisc_request_route(TAKE_PTR(route), link, rt);
499 if (r < 0)
500 return log_link_warning_errno(link, r, "Could not request prefix route: %m");
501
502 return 0;
503 }
504
505 static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) {
506 unsigned prefixlen;
507 struct in6_addr a;
508 uint8_t flags;
509 int r;
510
511 assert(link);
512 assert(link->network);
513 assert(rt);
514
515 r = sd_ndisc_router_prefix_get_address(rt, &a);
516 if (r < 0)
517 return log_link_warning_errno(link, r, "Failed to get prefix address: %m");
518
519 /* RFC 4861 Section 4.6.2:
520 * A router SHOULD NOT send a prefix option for the link-local prefix and a host SHOULD ignore such
521 * a prefix option. */
522 if (in6_addr_is_link_local(&a)) {
523 log_link_debug(link, "Received link-local prefix, ignoring autonomous prefix.");
524 return 0;
525 }
526
527 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
528 if (r < 0)
529 return log_link_warning_errno(link, r, "Failed to get prefix length: %m");
530
531 if (in6_prefix_is_filtered(&a, prefixlen, link->network->ndisc_allow_listed_prefix, link->network->ndisc_deny_listed_prefix)) {
532 if (DEBUG_LOGGING)
533 log_link_debug(link, "Prefix '%s' is %s, ignoring",
534 !set_isempty(link->network->ndisc_allow_listed_prefix) ? "not in allow list"
535 : "in deny list",
536 IN6_ADDR_PREFIX_TO_STRING(&a, prefixlen));
537 return 0;
538 }
539
540 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
541 if (r < 0)
542 return log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m");
543
544 if (FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) {
545 r = ndisc_router_process_onlink_prefix(link, rt);
546 if (r < 0)
547 return r;
548 }
549
550 if (FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) {
551 r = ndisc_router_process_autonomous_prefix(link, rt);
552 if (r < 0)
553 return r;
554 }
555
556 return 0;
557 }
558
559 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
560 _cleanup_(route_freep) Route *route = NULL;
561 unsigned preference, prefixlen;
562 struct in6_addr gateway, dst;
563 uint32_t lifetime_sec;
564 usec_t timestamp_usec;
565 int r;
566
567 assert(link);
568
569 if (!link->network->ipv6_accept_ra_use_route_prefix)
570 return 0;
571
572 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime_sec);
573 if (r < 0)
574 return log_link_warning_errno(link, r, "Failed to get route lifetime from RA: %m");
575
576 r = sd_ndisc_router_route_get_address(rt, &dst);
577 if (r < 0)
578 return log_link_warning_errno(link, r, "Failed to get route destination address: %m");
579
580 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
581 if (r < 0)
582 return log_link_warning_errno(link, r, "Failed to get route prefix length: %m");
583
584 if (in6_addr_is_null(&dst) && prefixlen == 0) {
585 log_link_debug(link, "Route prefix is ::/0, ignoring");
586 return 0;
587 }
588
589 if (in6_prefix_is_filtered(&dst, prefixlen,
590 link->network->ndisc_allow_listed_route_prefix,
591 link->network->ndisc_deny_listed_route_prefix)) {
592
593 if (DEBUG_LOGGING)
594 log_link_debug(link, "Route prefix %s is %s, ignoring",
595 !set_isempty(link->network->ndisc_allow_listed_route_prefix) ? "not in allow list"
596 : "in deny list",
597 IN6_ADDR_PREFIX_TO_STRING(&dst, prefixlen));
598 return 0;
599 }
600
601 r = sd_ndisc_router_get_address(rt, &gateway);
602 if (r < 0)
603 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
604
605 if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
606 if (DEBUG_LOGGING)
607 log_link_debug(link, "Advertised route gateway %s is local to the link, ignoring route",
608 IN6_ADDR_TO_STRING(&gateway));
609 return 0;
610 }
611
612 r = sd_ndisc_router_route_get_preference(rt, &preference);
613 if (r == -ENOTSUP) {
614 log_link_debug_errno(link, r, "Received route prefix with unsupported preference, ignoring: %m");
615 return 0;
616 }
617 if (r < 0)
618 return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
619
620 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
621 if (r < 0)
622 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
623
624 r = route_new(&route);
625 if (r < 0)
626 return log_oom();
627
628 route->family = AF_INET6;
629 route->pref = preference;
630 route->gw.in6 = gateway;
631 route->gw_family = AF_INET6;
632 route->dst.in6 = dst;
633 route->dst_prefixlen = prefixlen;
634 route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
635
636 r = ndisc_request_route(TAKE_PTR(route), link, rt);
637 if (r < 0)
638 return log_link_warning_errno(link, r, "Could not request additional route: %m");
639
640 return 0;
641 }
642
643 static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
644 siphash24_compress(&x->address, sizeof(x->address), state);
645 }
646
647 static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
648 return memcmp(&a->address, &b->address, sizeof(a->address));
649 }
650
651 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
652 ndisc_rdnss_hash_ops,
653 NDiscRDNSS,
654 ndisc_rdnss_hash_func,
655 ndisc_rdnss_compare_func,
656 free);
657
658 static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
659 usec_t lifetime_usec, timestamp_usec;
660 uint32_t lifetime_sec;
661 const struct in6_addr *a;
662 struct in6_addr router;
663 bool updated = false, logged_about_too_many = false;
664 int n, r;
665
666 assert(link);
667 assert(link->network);
668 assert(rt);
669
670 if (!link->network->ipv6_accept_ra_use_dns)
671 return 0;
672
673 r = sd_ndisc_router_get_address(rt, &router);
674 if (r < 0)
675 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
676
677 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
678 if (r < 0)
679 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
680
681 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime_sec);
682 if (r < 0)
683 return log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
684
685 lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
686
687 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
688 if (n < 0)
689 return log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m");
690
691 for (int j = 0; j < n; j++) {
692 _cleanup_free_ NDiscRDNSS *x = NULL;
693 NDiscRDNSS *rdnss, d = {
694 .address = a[j],
695 };
696
697 if (lifetime_usec == 0) {
698 /* The entry is outdated. */
699 free(set_remove(link->ndisc_rdnss, &d));
700 updated = true;
701 continue;
702 }
703
704 rdnss = set_get(link->ndisc_rdnss, &d);
705 if (rdnss) {
706 rdnss->router = router;
707 rdnss->lifetime_usec = lifetime_usec;
708 continue;
709 }
710
711 if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX) {
712 if (!logged_about_too_many)
713 log_link_warning(link, "Too many RDNSS records per link. Only first %u records will be used.", NDISC_RDNSS_MAX);
714 logged_about_too_many = true;
715 continue;
716 }
717
718 x = new(NDiscRDNSS, 1);
719 if (!x)
720 return log_oom();
721
722 *x = (NDiscRDNSS) {
723 .address = a[j],
724 .router = router,
725 .lifetime_usec = lifetime_usec,
726 };
727
728 r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
729 if (r < 0)
730 return log_oom();
731 assert(r > 0);
732
733 updated = true;
734 }
735
736 if (updated)
737 link_dirty(link);
738
739 return 0;
740 }
741
742 static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
743 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x), state);
744 }
745
746 static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
747 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
748 }
749
750 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
751 ndisc_dnssl_hash_ops,
752 NDiscDNSSL,
753 ndisc_dnssl_hash_func,
754 ndisc_dnssl_compare_func,
755 free);
756
757 static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
758 _cleanup_strv_free_ char **l = NULL;
759 usec_t lifetime_usec, timestamp_usec;
760 struct in6_addr router;
761 uint32_t lifetime_sec;
762 bool updated = false, logged_about_too_many = false;
763 int r;
764
765 assert(link);
766 assert(link->network);
767 assert(rt);
768
769 if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_NO)
770 return 0;
771
772 r = sd_ndisc_router_get_address(rt, &router);
773 if (r < 0)
774 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
775
776 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
777 if (r < 0)
778 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
779
780 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime_sec);
781 if (r < 0)
782 return log_link_warning_errno(link, r, "Failed to get DNSSL lifetime: %m");
783
784 lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
785
786 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
787 if (r < 0)
788 return log_link_warning_errno(link, r, "Failed to get DNSSL addresses: %m");
789
790 STRV_FOREACH(j, l) {
791 _cleanup_free_ NDiscDNSSL *s = NULL;
792 NDiscDNSSL *dnssl;
793
794 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1);
795 if (!s)
796 return log_oom();
797
798 strcpy(NDISC_DNSSL_DOMAIN(s), *j);
799
800 if (lifetime_usec == 0) {
801 /* The entry is outdated. */
802 free(set_remove(link->ndisc_dnssl, s));
803 updated = true;
804 continue;
805 }
806
807 dnssl = set_get(link->ndisc_dnssl, s);
808 if (dnssl) {
809 dnssl->router = router;
810 dnssl->lifetime_usec = lifetime_usec;
811 continue;
812 }
813
814 if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX) {
815 if (!logged_about_too_many)
816 log_link_warning(link, "Too many DNSSL records per link. Only first %u records will be used.", NDISC_DNSSL_MAX);
817 logged_about_too_many = true;
818 continue;
819 }
820
821 s->router = router;
822 s->lifetime_usec = lifetime_usec;
823
824 r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
825 if (r < 0)
826 return log_oom();
827 assert(r > 0);
828
829 updated = true;
830 }
831
832 if (updated)
833 link_dirty(link);
834
835 return 0;
836 }
837
838 static NDiscCaptivePortal* ndisc_captive_portal_free(NDiscCaptivePortal *x) {
839 if (!x)
840 return NULL;
841
842 free(x->captive_portal);
843 return mfree(x);
844 }
845
846 DEFINE_TRIVIAL_CLEANUP_FUNC(NDiscCaptivePortal*, ndisc_captive_portal_free);
847
848 static void ndisc_captive_portal_hash_func(const NDiscCaptivePortal *x, struct siphash *state) {
849 assert(x);
850 siphash24_compress_string(x->captive_portal, state);
851 }
852
853 static int ndisc_captive_portal_compare_func(const NDiscCaptivePortal *a, const NDiscCaptivePortal *b) {
854 assert(a);
855 assert(b);
856 return strcmp_ptr(a->captive_portal, b->captive_portal);
857 }
858
859 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
860 ndisc_captive_portal_hash_ops,
861 NDiscCaptivePortal,
862 ndisc_captive_portal_hash_func,
863 ndisc_captive_portal_compare_func,
864 ndisc_captive_portal_free);
865
866 static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt) {
867 _cleanup_(ndisc_captive_portal_freep) NDiscCaptivePortal *new_entry = NULL;
868 _cleanup_free_ char *captive_portal = NULL;
869 usec_t lifetime_usec, timestamp_usec;
870 NDiscCaptivePortal *exist;
871 struct in6_addr router;
872 uint16_t lifetime_sec;
873 const char *uri;
874 size_t len;
875 int r;
876
877 assert(link);
878 assert(link->network);
879 assert(rt);
880
881 if (!link->network->ipv6_accept_ra_use_captive_portal)
882 return 0;
883
884 r = sd_ndisc_router_get_address(rt, &router);
885 if (r < 0)
886 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
887
888 /* RFC 4861 section 4.2. states that the lifetime in the message header should be used only for the
889 * default gateway, but the captive portal option does not have a lifetime field, hence, we use the
890 * main lifetime for the portal. */
891 r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec);
892 if (r < 0)
893 return log_link_warning_errno(link, r, "Failed to get lifetime of RA message: %m");
894
895 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
896 if (r < 0)
897 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
898
899 lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec);
900
901 r = sd_ndisc_router_captive_portal_get_uri(rt, &uri, &len);
902 if (r < 0)
903 return log_link_warning_errno(link, r, "Failed to get captive portal from RA: %m");
904
905 if (len == 0)
906 return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBADMSG), "Received empty captive portal, ignoring.");
907
908 r = make_cstring(uri, len, MAKE_CSTRING_REFUSE_TRAILING_NUL, &captive_portal);
909 if (r < 0)
910 return log_link_warning_errno(link, r, "Failed to convert captive portal URI: %m");
911
912 if (!in_charset(captive_portal, URI_VALID))
913 return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBADMSG), "Received invalid captive portal, ignoring.");
914
915 if (lifetime_usec == 0) {
916 /* Drop the portal with zero lifetime. */
917 ndisc_captive_portal_free(set_remove(link->ndisc_captive_portals,
918 &(NDiscCaptivePortal) {
919 .captive_portal = captive_portal,
920 }));
921 return 0;
922 }
923
924 exist = set_get(link->ndisc_captive_portals,
925 &(NDiscCaptivePortal) {
926 .captive_portal = captive_portal,
927 });
928 if (exist) {
929 /* update existing entry */
930 exist->router = router;
931 exist->lifetime_usec = lifetime_usec;
932 return 1;
933 }
934
935 if (set_size(link->ndisc_captive_portals) >= NDISC_CAPTIVE_PORTAL_MAX) {
936 NDiscCaptivePortal *c, *target = NULL;
937
938 /* Find the portal who has the minimal lifetime and drop it to store new one. */
939 SET_FOREACH(c, link->ndisc_captive_portals)
940 if (!target || c->lifetime_usec < target->lifetime_usec)
941 target = c;
942
943 assert(target);
944 assert(set_remove(link->ndisc_captive_portals, target) == target);
945 ndisc_captive_portal_free(target);
946 }
947
948 new_entry = new(NDiscCaptivePortal, 1);
949 if (!new_entry)
950 return log_oom();
951
952 *new_entry = (NDiscCaptivePortal) {
953 .router = router,
954 .lifetime_usec = lifetime_usec,
955 .captive_portal = TAKE_PTR(captive_portal),
956 };
957
958 r = set_ensure_put(&link->ndisc_captive_portals, &ndisc_captive_portal_hash_ops, new_entry);
959 if (r < 0)
960 return log_oom();
961 assert(r > 0);
962 TAKE_PTR(new_entry);
963
964 link_dirty(link);
965 return 1;
966 }
967
968 static void ndisc_pref64_hash_func(const NDiscPREF64 *x, struct siphash *state) {
969 assert(x);
970
971 siphash24_compress(&x->prefix_len, sizeof(x->prefix_len), state);
972 siphash24_compress(&x->prefix, sizeof(x->prefix), state);
973 }
974
975 static int ndisc_pref64_compare_func(const NDiscPREF64 *a, const NDiscPREF64 *b) {
976 int r;
977
978 assert(a);
979 assert(b);
980
981 r = CMP(a->prefix_len, b->prefix_len);
982 if (r != 0)
983 return r;
984
985 return memcmp(&a->prefix, &b->prefix, sizeof(a->prefix));
986 }
987
988 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
989 ndisc_pref64_hash_ops,
990 NDiscPREF64,
991 ndisc_pref64_hash_func,
992 ndisc_pref64_compare_func,
993 mfree);
994
995 static int ndisc_router_process_pref64(Link *link, sd_ndisc_router *rt) {
996 _cleanup_free_ NDiscPREF64 *new_entry = NULL;
997 usec_t lifetime_usec, timestamp_usec;
998 struct in6_addr a, router;
999 uint16_t lifetime_sec;
1000 unsigned prefix_len;
1001 NDiscPREF64 *exist;
1002 int r;
1003
1004 assert(link);
1005 assert(link->network);
1006 assert(rt);
1007
1008 if (!link->network->ipv6_accept_ra_use_pref64)
1009 return 0;
1010
1011 r = sd_ndisc_router_get_address(rt, &router);
1012 if (r < 0)
1013 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
1014
1015 r = sd_ndisc_router_prefix64_get_prefix(rt, &a);
1016 if (r < 0)
1017 return log_link_warning_errno(link, r, "Failed to get pref64 prefix: %m");
1018
1019 r = sd_ndisc_router_prefix64_get_prefixlen(rt, &prefix_len);
1020 if (r < 0)
1021 return log_link_warning_errno(link, r, "Failed to get pref64 prefix length: %m");
1022
1023 r = sd_ndisc_router_prefix64_get_lifetime_sec(rt, &lifetime_sec);
1024 if (r < 0)
1025 return log_link_warning_errno(link, r, "Failed to get pref64 prefix lifetime: %m");
1026
1027 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
1028 if (r < 0)
1029 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
1030
1031 lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec);
1032
1033 if (lifetime_usec == 0) {
1034 free(set_remove(link->ndisc_pref64,
1035 &(NDiscPREF64) {
1036 .prefix = a,
1037 .prefix_len = prefix_len
1038 }));
1039 return 0;
1040 }
1041
1042 exist = set_get(link->ndisc_pref64,
1043 &(NDiscPREF64) {
1044 .prefix = a,
1045 .prefix_len = prefix_len
1046 });
1047 if (exist) {
1048 /* update existing entry */
1049 exist->router = router;
1050 exist->lifetime_usec = lifetime_usec;
1051 return 0;
1052 }
1053
1054 new_entry = new(NDiscPREF64, 1);
1055 if (!new_entry)
1056 return log_oom();
1057
1058 *new_entry = (NDiscPREF64) {
1059 .router = router,
1060 .lifetime_usec = lifetime_usec,
1061 .prefix = a,
1062 .prefix_len = prefix_len,
1063 };
1064
1065 r = set_ensure_put(&link->ndisc_pref64, &ndisc_pref64_hash_ops, new_entry);
1066 if (r < 0)
1067 return log_oom();
1068
1069 assert(r > 0);
1070 TAKE_PTR(new_entry);
1071
1072 return 0;
1073 }
1074
1075 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
1076 size_t n_captive_portal = 0;
1077 int r;
1078
1079 assert(link);
1080 assert(link->network);
1081 assert(rt);
1082
1083 for (r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
1084 uint8_t type;
1085
1086 if (r < 0)
1087 return log_link_warning_errno(link, r, "Failed to iterate through options: %m");
1088 if (r == 0) /* EOF */
1089 return 0;
1090
1091 r = sd_ndisc_router_option_get_type(rt, &type);
1092 if (r < 0)
1093 return log_link_warning_errno(link, r, "Failed to get RA option type: %m");
1094
1095 switch (type) {
1096 case SD_NDISC_OPTION_PREFIX_INFORMATION:
1097 r = ndisc_router_process_prefix(link, rt);
1098 break;
1099
1100 case SD_NDISC_OPTION_ROUTE_INFORMATION:
1101 r = ndisc_router_process_route(link, rt);
1102 break;
1103
1104 case SD_NDISC_OPTION_RDNSS:
1105 r = ndisc_router_process_rdnss(link, rt);
1106 break;
1107
1108 case SD_NDISC_OPTION_DNSSL:
1109 r = ndisc_router_process_dnssl(link, rt);
1110 break;
1111 case SD_NDISC_OPTION_CAPTIVE_PORTAL:
1112 if (n_captive_portal > 0) {
1113 if (n_captive_portal == 1)
1114 log_link_notice(link, "Received RA with multiple captive portals, only using the first one.");
1115
1116 n_captive_portal++;
1117 continue;
1118 }
1119 r = ndisc_router_process_captive_portal(link, rt);
1120 if (r > 0)
1121 n_captive_portal++;
1122 break;
1123 case SD_NDISC_OPTION_PREF64:
1124 r = ndisc_router_process_pref64(link, rt);
1125 break;
1126 }
1127 if (r < 0 && r != -EBADMSG)
1128 return r;
1129 }
1130 }
1131
1132 static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
1133 bool updated = false;
1134 NDiscDNSSL *dnssl;
1135 NDiscRDNSS *rdnss;
1136 NDiscCaptivePortal *cp;
1137 Address *address;
1138 Route *route;
1139 int r = 0, k;
1140
1141 assert(link);
1142
1143 /* If an address or friends is already assigned, but not valid anymore, then refuse to update it,
1144 * and let's immediately remove it.
1145 * See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by honoring all
1146 * valid lifetimes to improve the reaction of SLAAC to renumbering events.
1147 * See draft-ietf-6man-slaac-renum-02, section 4.2. */
1148
1149 SET_FOREACH(route, link->routes) {
1150 if (route->source != NETWORK_CONFIG_SOURCE_NDISC)
1151 continue;
1152
1153 if (route->lifetime_usec >= timestamp_usec)
1154 continue; /* the route is still valid */
1155
1156 k = route_remove_and_drop(route);
1157 if (k < 0)
1158 r = log_link_warning_errno(link, k, "Failed to remove outdated SLAAC route, ignoring: %m");
1159 }
1160
1161 SET_FOREACH(address, link->addresses) {
1162 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
1163 continue;
1164
1165 if (address->lifetime_valid_usec >= timestamp_usec)
1166 continue; /* the address is still valid */
1167
1168 k = address_remove_and_drop(address);
1169 if (k < 0)
1170 r = log_link_warning_errno(link, k, "Failed to remove outdated SLAAC address, ignoring: %m");
1171 }
1172
1173 SET_FOREACH(rdnss, link->ndisc_rdnss) {
1174 if (rdnss->lifetime_usec >= timestamp_usec)
1175 continue; /* the DNS server is still valid */
1176
1177 free(set_remove(link->ndisc_rdnss, rdnss));
1178 updated = true;
1179 }
1180
1181 SET_FOREACH(dnssl, link->ndisc_dnssl) {
1182 if (dnssl->lifetime_usec >= timestamp_usec)
1183 continue; /* the DNS domain is still valid */
1184
1185 free(set_remove(link->ndisc_dnssl, dnssl));
1186 updated = true;
1187 }
1188
1189 SET_FOREACH(cp, link->ndisc_captive_portals) {
1190 if (cp->lifetime_usec >= timestamp_usec)
1191 continue; /* the captive portal is still valid */
1192
1193 ndisc_captive_portal_free(set_remove(link->ndisc_captive_portals, cp));
1194 updated = true;
1195 }
1196
1197 if (updated)
1198 link_dirty(link);
1199
1200 return r;
1201 }
1202
1203 static int ndisc_setup_expire(Link *link);
1204
1205 static int ndisc_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
1206 Link *link = ASSERT_PTR(userdata);
1207 usec_t now_usec;
1208
1209 assert(link->manager);
1210
1211 assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
1212
1213 (void) ndisc_drop_outdated(link, now_usec);
1214 (void) ndisc_setup_expire(link);
1215 return 0;
1216 }
1217
1218 static int ndisc_setup_expire(Link *link) {
1219 usec_t lifetime_usec = USEC_INFINITY;
1220 NDiscCaptivePortal *cp;
1221 NDiscDNSSL *dnssl;
1222 NDiscRDNSS *rdnss;
1223 Address *address;
1224 Route *route;
1225 int r;
1226
1227 assert(link);
1228 assert(link->manager);
1229
1230 SET_FOREACH(route, link->routes) {
1231 if (route->source != NETWORK_CONFIG_SOURCE_NDISC)
1232 continue;
1233
1234 if (!route_exists(route))
1235 continue;
1236
1237 lifetime_usec = MIN(lifetime_usec, route->lifetime_usec);
1238 }
1239
1240 SET_FOREACH(address, link->addresses) {
1241 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
1242 continue;
1243
1244 if (!address_exists(address))
1245 continue;
1246
1247 lifetime_usec = MIN(lifetime_usec, address->lifetime_valid_usec);
1248 }
1249
1250 SET_FOREACH(rdnss, link->ndisc_rdnss)
1251 lifetime_usec = MIN(lifetime_usec, rdnss->lifetime_usec);
1252
1253 SET_FOREACH(dnssl, link->ndisc_dnssl)
1254 lifetime_usec = MIN(lifetime_usec, dnssl->lifetime_usec);
1255
1256 SET_FOREACH(cp, link->ndisc_captive_portals)
1257 lifetime_usec = MIN(lifetime_usec, cp->lifetime_usec);
1258
1259 if (lifetime_usec == USEC_INFINITY)
1260 return 0;
1261
1262 r = event_reset_time(link->manager->event, &link->ndisc_expire, CLOCK_BOOTTIME,
1263 lifetime_usec, 0, ndisc_expire_handler, link, 0, "ndisc-expiration", true);
1264 if (r < 0)
1265 return log_link_warning_errno(link, r, "Failed to update expiration timer for ndisc: %m");
1266
1267 return 0;
1268 }
1269
1270 static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) {
1271 int r;
1272
1273 assert(link);
1274 assert(link->network);
1275
1276 switch (link->network->ipv6_accept_ra_start_dhcp6_client) {
1277 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO:
1278 return 0;
1279
1280 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES: {
1281 uint64_t flags;
1282
1283 r = sd_ndisc_router_get_flags(rt, &flags);
1284 if (r < 0)
1285 return log_link_warning_errno(link, r, "Failed to get RA flags: %m");
1286
1287 if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) == 0)
1288 return 0;
1289
1290 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags.
1291 * Note, if both "managed" and "other configuration" bits are set, then ignore
1292 * "other configuration" bit. See RFC 4861. */
1293 r = dhcp6_start_on_ra(link, !(flags & ND_RA_FLAG_MANAGED));
1294 break;
1295 }
1296 case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS:
1297 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in solicit mode
1298 * even if the router flags have neither M nor O flags. */
1299 r = dhcp6_start_on_ra(link, /* information_request = */ false);
1300 break;
1301
1302 default:
1303 assert_not_reached();
1304 }
1305
1306 if (r < 0)
1307 return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
1308
1309 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
1310 return 0;
1311 }
1312
1313 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
1314 struct in6_addr router;
1315 usec_t timestamp_usec;
1316 int r;
1317
1318 assert(link);
1319 assert(link->network);
1320 assert(link->manager);
1321 assert(rt);
1322
1323 r = sd_ndisc_router_get_address(rt, &router);
1324 if (r == -ENODATA) {
1325 log_link_debug(link, "Received RA without router address, ignoring.");
1326 return 0;
1327 }
1328 if (r < 0)
1329 return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
1330
1331 if (in6_prefix_is_filtered(&router, 128, link->network->ndisc_allow_listed_router, link->network->ndisc_deny_listed_router)) {
1332 if (DEBUG_LOGGING) {
1333 if (!set_isempty(link->network->ndisc_allow_listed_router))
1334 log_link_debug(link, "Router %s is not in allow list, ignoring.", IN6_ADDR_TO_STRING(&router));
1335 else
1336 log_link_debug(link, "Router %s is in deny list, ignoring.", IN6_ADDR_TO_STRING(&router));
1337 }
1338 return 0;
1339 }
1340
1341 r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
1342 if (r == -ENODATA) {
1343 log_link_debug(link, "Received RA without timestamp, ignoring.");
1344 return 0;
1345 }
1346 if (r < 0)
1347 return r;
1348
1349 r = ndisc_drop_outdated(link, timestamp_usec);
1350 if (r < 0)
1351 return r;
1352
1353 r = ndisc_start_dhcp6_client(link, rt);
1354 if (r < 0)
1355 return r;
1356
1357 r = ndisc_router_process_default(link, rt);
1358 if (r < 0)
1359 return r;
1360
1361 r = ndisc_router_process_options(link, rt);
1362 if (r < 0)
1363 return r;
1364
1365 r = ndisc_setup_expire(link);
1366 if (r < 0)
1367 return r;
1368
1369 if (link->ndisc_messages == 0)
1370 link->ndisc_configured = true;
1371 else
1372 log_link_debug(link, "Setting SLAAC addresses and router.");
1373
1374 if (!link->ndisc_configured)
1375 link_set_state(link, LINK_STATE_CONFIGURING);
1376
1377 link_check_ready(link);
1378 return 0;
1379 }
1380
1381 static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
1382 Link *link = ASSERT_PTR(userdata);
1383 int r;
1384
1385 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1386 return;
1387
1388 switch (event) {
1389
1390 case SD_NDISC_EVENT_ROUTER:
1391 r = ndisc_router_handler(link, rt);
1392 if (r < 0 && r != -EBADMSG) {
1393 link_enter_failed(link);
1394 return;
1395 }
1396 break;
1397
1398 case SD_NDISC_EVENT_TIMEOUT:
1399 log_link_debug(link, "NDisc handler get timeout event");
1400 if (link->ndisc_messages == 0) {
1401 link->ndisc_configured = true;
1402 link_check_ready(link);
1403 }
1404 break;
1405 default:
1406 assert_not_reached();
1407 }
1408 }
1409
1410 static int ndisc_configure(Link *link) {
1411 int r;
1412
1413 assert(link);
1414
1415 if (!link_ipv6_accept_ra_enabled(link))
1416 return 0;
1417
1418 if (link->ndisc)
1419 return -EBUSY; /* Already configured. */
1420
1421 r = sd_ndisc_new(&link->ndisc);
1422 if (r < 0)
1423 return r;
1424
1425 r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
1426 if (r < 0)
1427 return r;
1428
1429 if (link->hw_addr.length == ETH_ALEN) {
1430 r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.ether);
1431 if (r < 0)
1432 return r;
1433 }
1434
1435 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
1436 if (r < 0)
1437 return r;
1438
1439 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
1440 if (r < 0)
1441 return r;
1442
1443 return 0;
1444 }
1445
1446 int ndisc_start(Link *link) {
1447 int r;
1448
1449 assert(link);
1450
1451 if (!link->ndisc || !link->dhcp6_client)
1452 return 0;
1453
1454 if (!link_has_carrier(link))
1455 return 0;
1456
1457 if (in6_addr_is_null(&link->ipv6ll_address))
1458 return 0;
1459
1460 log_link_debug(link, "Discovering IPv6 routers");
1461
1462 r = sd_ndisc_start(link->ndisc);
1463 if (r < 0)
1464 return r;
1465
1466 return 1;
1467 }
1468
1469 static int ndisc_process_request(Request *req, Link *link, void *userdata) {
1470 int r;
1471
1472 assert(link);
1473
1474 if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false))
1475 return 0;
1476
1477 r = ndisc_configure(link);
1478 if (r < 0)
1479 return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Discovery: %m");
1480
1481 r = ndisc_start(link);
1482 if (r < 0)
1483 return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
1484
1485 log_link_debug(link, "IPv6 Router Discovery is configured%s.",
1486 r > 0 ? " and started" : "");
1487 return 1;
1488 }
1489
1490 int link_request_ndisc(Link *link) {
1491 int r;
1492
1493 assert(link);
1494
1495 if (!link_ipv6_accept_ra_enabled(link))
1496 return 0;
1497
1498 if (link->ndisc)
1499 return 0;
1500
1501 r = link_queue_request(link, REQUEST_TYPE_NDISC, ndisc_process_request, NULL);
1502 if (r < 0)
1503 return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m");
1504
1505 log_link_debug(link, "Requested configuring of the IPv6 Router Discovery.");
1506 return 0;
1507 }
1508
1509 int ndisc_stop(Link *link) {
1510 assert(link);
1511
1512 link->ndisc_expire = sd_event_source_disable_unref(link->ndisc_expire);
1513
1514 return sd_ndisc_stop(link->ndisc);
1515 }
1516
1517
1518 void ndisc_flush(Link *link) {
1519 assert(link);
1520
1521 /* Remove all RDNSS, DNSSL, and Captive Portal entries, without exception. */
1522
1523 link->ndisc_rdnss = set_free(link->ndisc_rdnss);
1524 link->ndisc_dnssl = set_free(link->ndisc_dnssl);
1525 link->ndisc_captive_portals = set_free(link->ndisc_captive_portals);
1526 link->ndisc_pref64 = set_free(link->ndisc_pref64);
1527 }
1528
1529 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1530 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1531 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1532 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1533 };
1534
1535 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);
1536
1537 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains, dhcp_use_domains, DHCPUseDomains,
1538 "Failed to parse UseDomains= setting");
1539 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
1540 "Failed to parse DHCPv6Client= setting");