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