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