]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-ndisc.c
network: change order of dropping network configs
[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 7#include <netinet/icmp6.h>
b8162cd2 8#include <net/if_arp.h>
062c020f 9#include <linux/if.h>
a13c50e7 10
a13c50e7
TG
11#include "sd-ndisc.h"
12
d909e4af 13#include "missing_network.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"
3b5a4fc6 18#include "networkd-state-file.h"
ac24e418 19#include "string-table.h"
5f506a55 20#include "string-util.h"
51517f9e 21#include "strv.h"
1e7a0e21
LP
22
23#define NDISC_DNSSL_MAX 64U
24#define NDISC_RDNSS_MAX 64U
6554550f 25#define NDISC_PREFIX_LFT_MIN 7200U
fe307276 26
5f506a55
SS
27#define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
28
29/* https://tools.ietf.org/html/rfc5453 */
30/* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */
31
32#define SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } })
33#define SUBNET_ROUTER_ANYCAST_PREFIXLEN 8
34#define RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x02, 0x00, 0x5E, 0xFF, 0xFE } })
35#define RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN 5
36#define RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291 ((struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } })
37#define RESERVED_SUBNET_ANYCAST_PREFIXLEN 7
38
39#define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
40
062c020f
YW
41bool link_ipv6_accept_ra_enabled(Link *link) {
42 assert(link);
43
44 if (!socket_ipv6_is_supported())
45 return false;
46
47 if (link->flags & IFF_LOOPBACK)
48 return false;
49
50 if (!link->network)
51 return false;
52
53 if (!link_ipv6ll_enabled(link))
54 return false;
55
3773eb54
YW
56 assert(link->network->ipv6_accept_ra >= 0);
57 return link->network->ipv6_accept_ra;
58}
59
60void network_adjust_ipv6_accept_ra(Network *network) {
61 assert(network);
62
63 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
64 if (network->ipv6_accept_ra > 0)
65 log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link local addressing is disabled or not supported. "
66 "Disabling IPv6AcceptRA=.", network->filename);
67 network->ipv6_accept_ra = false;
68 }
69
70 if (network->ipv6_accept_ra < 0)
062c020f 71 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
3773eb54 72 network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6);
de6b6ff8 73
75d26411
YW
74 /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
75 * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
76 if (!set_isempty(network->ndisc_allow_listed_router))
77 network->ndisc_deny_listed_router = set_free_free(network->ndisc_deny_listed_router);
de6b6ff8
SS
78 if (!set_isempty(network->ndisc_allow_listed_prefix))
79 network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix);
80 if (!set_isempty(network->ndisc_allow_listed_route_prefix))
81 network->ndisc_deny_listed_route_prefix = set_free_free(network->ndisc_deny_listed_route_prefix);
062c020f
YW
82}
83
50550722 84static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force);
69203fba
YW
85
86static int ndisc_address_callback(Address *address) {
50550722
YW
87 struct in6_addr router = {};
88 NDiscAddress *n;
69203fba
YW
89
90 assert(address);
91 assert(address->link);
b8ce3b44 92 assert(address->family == AF_INET6);
69203fba 93
90e74a66 94 SET_FOREACH(n, address->link->ndisc_addresses)
50550722
YW
95 if (n->address == address) {
96 router = n->router;
97 break;
98 }
99
94876904 100 if (in6_addr_is_null(&router)) {
50550722
YW
101 _cleanup_free_ char *buf = NULL;
102
b8ce3b44 103 (void) in6_addr_prefix_to_string(&address->in_addr.in6, address->prefixlen, &buf);
5380707a
YW
104 log_link_debug(address->link, "%s is called for %s, but it is already removed, ignoring.",
105 __func__, strna(buf));
50550722
YW
106 return 0;
107 }
108
69203fba 109 /* Make this called only once */
90e74a66 110 SET_FOREACH(n, address->link->ndisc_addresses)
b8ce3b44 111 if (in6_addr_equal(&n->router, &router))
50550722 112 n->address->callback = NULL;
69203fba 113
50550722 114 return ndisc_remove_old_one(address->link, &router, true);
69203fba
YW
115}
116
50550722
YW
117static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force) {
118 NDiscAddress *na;
119 NDiscRoute *nr;
b0b97766
YW
120 NDiscDNSSL *dnssl;
121 NDiscRDNSS *rdnss;
69203fba 122 int k, r = 0;
9092113d 123 bool updated = false;
69203fba
YW
124
125 assert(link);
50550722 126 assert(router);
69203fba
YW
127
128 if (!force) {
50550722 129 bool set_callback = false;
69203fba
YW
130
131 if (!link->ndisc_addresses_configured || !link->ndisc_routes_configured)
132 return 0;
133
90e74a66 134 SET_FOREACH(na, link->ndisc_addresses)
b8ce3b44 135 if (!na->marked && in6_addr_equal(&na->router, router)) {
50550722 136 set_callback = true;
69203fba
YW
137 break;
138 }
139
50550722 140 if (set_callback)
90e74a66 141 SET_FOREACH(na, link->ndisc_addresses)
50550722
YW
142 if (!na->marked && address_is_ready(na->address)) {
143 set_callback = false;
144 break;
145 }
146
69203fba 147 if (set_callback) {
90e74a66 148 SET_FOREACH(na, link->ndisc_addresses)
b8ce3b44 149 if (!na->marked && in6_addr_equal(&na->router, router))
50550722
YW
150 na->address->callback = ndisc_address_callback;
151
152 if (DEBUG_LOGGING) {
153 _cleanup_free_ char *buf = NULL;
154
b8ce3b44 155 (void) in6_addr_to_string(router, &buf);
50550722
YW
156 log_link_debug(link, "No SLAAC address obtained from %s is ready. "
157 "The old NDisc information will be removed later.",
158 strna(buf));
159 }
69203fba
YW
160 return 0;
161 }
162 }
163
50550722
YW
164 if (DEBUG_LOGGING) {
165 _cleanup_free_ char *buf = NULL;
166
b8ce3b44 167 (void) in6_addr_to_string(router, &buf);
50550722
YW
168 log_link_debug(link, "Removing old NDisc information obtained from %s.", strna(buf));
169 }
69203fba 170
90e74a66 171 SET_FOREACH(na, link->ndisc_addresses)
b8ce3b44 172 if (na->marked && in6_addr_equal(&na->router, router)) {
50550722
YW
173 k = address_remove(na->address, link, NULL);
174 if (k < 0)
175 r = k;
176 }
69203fba 177
90e74a66 178 SET_FOREACH(nr, link->ndisc_routes)
b8ce3b44 179 if (nr->marked && in6_addr_equal(&nr->router, router)) {
ad208fac 180 k = route_remove(nr->route, NULL, link, NULL);
50550722
YW
181 if (k < 0)
182 r = k;
183 }
69203fba 184
90e74a66 185 SET_FOREACH(rdnss, link->ndisc_rdnss)
b8ce3b44 186 if (rdnss->marked && in6_addr_equal(&rdnss->router, router)) {
b0b97766 187 free(set_remove(link->ndisc_rdnss, rdnss));
9092113d
YW
188 updated = true;
189 }
b0b97766 190
90e74a66 191 SET_FOREACH(dnssl, link->ndisc_dnssl)
b8ce3b44 192 if (dnssl->marked && in6_addr_equal(&dnssl->router, router)) {
b0b97766 193 free(set_remove(link->ndisc_dnssl, dnssl));
9092113d
YW
194 updated = true;
195 }
196
197 if (updated)
198 link_dirty(link);
b0b97766 199
69203fba
YW
200 return r;
201}
202
50550722
YW
203static int ndisc_remove_old(Link *link) {
204 _cleanup_set_free_free_ Set *routers = NULL;
205 _cleanup_free_ struct in6_addr *router = NULL;
206 struct in6_addr *a;
207 NDiscAddress *na;
208 NDiscRoute *nr;
209 NDiscDNSSL *dnssl;
210 NDiscRDNSS *rdnss;
50550722
YW
211 int k, r;
212
213 assert(link);
214
215 routers = set_new(&in6_addr_hash_ops);
216 if (!routers)
217 return -ENOMEM;
218
90e74a66 219 SET_FOREACH(na, link->ndisc_addresses)
50550722
YW
220 if (!set_contains(routers, &na->router)) {
221 router = newdup(struct in6_addr, &na->router, 1);
222 if (!router)
223 return -ENOMEM;
224
225 r = set_put(routers, router);
226 if (r < 0)
227 return r;
228
229 assert(r > 0);
230 TAKE_PTR(router);
231 }
232
90e74a66 233 SET_FOREACH(nr, link->ndisc_routes)
50550722
YW
234 if (!set_contains(routers, &nr->router)) {
235 router = newdup(struct in6_addr, &nr->router, 1);
236 if (!router)
237 return -ENOMEM;
238
239 r = set_put(routers, router);
240 if (r < 0)
241 return r;
242
243 assert(r > 0);
244 TAKE_PTR(router);
245 }
246
90e74a66 247 SET_FOREACH(rdnss, link->ndisc_rdnss)
50550722
YW
248 if (!set_contains(routers, &rdnss->router)) {
249 router = newdup(struct in6_addr, &rdnss->router, 1);
250 if (!router)
251 return -ENOMEM;
252
253 r = set_put(routers, router);
254 if (r < 0)
255 return r;
256
257 assert(r > 0);
258 TAKE_PTR(router);
259 }
260
90e74a66 261 SET_FOREACH(dnssl, link->ndisc_dnssl)
50550722
YW
262 if (!set_contains(routers, &dnssl->router)) {
263 router = newdup(struct in6_addr, &dnssl->router, 1);
264 if (!router)
265 return -ENOMEM;
266
267 r = set_put(routers, router);
268 if (r < 0)
269 return r;
270
271 assert(r > 0);
272 TAKE_PTR(router);
273 }
274
275 r = 0;
90e74a66 276 SET_FOREACH(a, routers) {
50550722
YW
277 k = ndisc_remove_old_one(link, a, false);
278 if (k < 0)
279 r = k;
280 }
281
282 return r;
283}
284
285static void ndisc_route_hash_func(const NDiscRoute *x, struct siphash *state) {
286 route_hash_func(x->route, state);
287}
288
289static int ndisc_route_compare_func(const NDiscRoute *a, const NDiscRoute *b) {
290 return route_compare_func(a->route, b->route);
291}
292
293DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
294 ndisc_route_hash_ops,
295 NDiscRoute,
296 ndisc_route_hash_func,
297 ndisc_route_compare_func,
298 free);
299
d98c546d 300static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
3b015d40
TG
301 int r;
302
303 assert(link);
d98c546d 304 assert(link->ndisc_routes_messages > 0);
3b015d40 305
d98c546d 306 link->ndisc_routes_messages--;
3b015d40 307
4ff296b0
YW
308 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
309 return 1;
310
3b015d40 311 r = sd_netlink_message_get_errno(m);
4ff296b0 312 if (r < 0 && r != -EEXIST) {
d98c546d 313 log_link_message_error_errno(link, m, r, "Could not set NDisc route");
4ff296b0
YW
314 link_enter_failed(link);
315 return 1;
316 }
3b015d40 317
d98c546d
YW
318 if (link->ndisc_routes_messages == 0) {
319 log_link_debug(link, "NDisc routes set.");
320 link->ndisc_routes_configured = true;
69203fba 321
50550722 322 r = ndisc_remove_old(link);
69203fba
YW
323 if (r < 0) {
324 link_enter_failed(link);
325 return 1;
326 }
327
3b015d40
TG
328 link_check_ready(link);
329 }
330
331 return 1;
332}
333
50550722
YW
334static int ndisc_route_configure(Route *route, Link *link, sd_ndisc_router *rt) {
335 _cleanup_free_ NDiscRoute *nr = NULL;
336 NDiscRoute *nr_exist;
337 struct in6_addr router;
338 Route *ret;
339 int r;
340
341 assert(route);
342 assert(link);
343 assert(rt);
344
345 r = route_configure(route, link, ndisc_route_handler, &ret);
346 if (r < 0)
347 return log_link_error_errno(link, r, "Failed to set NDisc route: %m");
24b445c2
YW
348 if (r > 0)
349 link->ndisc_routes_configured = false;
50550722
YW
350
351 link->ndisc_routes_messages++;
352
353 r = sd_ndisc_router_get_address(rt, &router);
354 if (r < 0)
355 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
356
357 nr = new(NDiscRoute, 1);
358 if (!nr)
359 return log_oom();
360
361 *nr = (NDiscRoute) {
362 .router = router,
363 .route = ret,
364 };
365
366 nr_exist = set_get(link->ndisc_routes, nr);
367 if (nr_exist) {
368 nr_exist->marked = false;
369 nr_exist->router = router;
370 return 0;
371 }
372
373 r = set_ensure_put(&link->ndisc_routes, &ndisc_route_hash_ops, nr);
374 if (r < 0)
375 return log_link_error_errno(link, r, "Failed to store NDisc SLAAC route: %m");
376 assert(r > 0);
377 TAKE_PTR(nr);
378
379 return 0;
380}
381
382static void ndisc_address_hash_func(const NDiscAddress *x, struct siphash *state) {
383 address_hash_func(x->address, state);
384}
385
386static int ndisc_address_compare_func(const NDiscAddress *a, const NDiscAddress *b) {
387 return address_compare_func(a->address, b->address);
388}
389
390DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
391 ndisc_address_hash_ops,
392 NDiscAddress,
393 ndisc_address_hash_func,
394 ndisc_address_compare_func,
395 free);
396
d98c546d 397static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
73854ba1
YW
398 int r;
399
400 assert(link);
d98c546d 401 assert(link->ndisc_addresses_messages > 0);
73854ba1 402
d98c546d 403 link->ndisc_addresses_messages--;
73854ba1 404
4ff296b0
YW
405 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
406 return 1;
407
73854ba1 408 r = sd_netlink_message_get_errno(m);
4ff296b0 409 if (r < 0 && r != -EEXIST) {
d98c546d 410 log_link_message_error_errno(link, m, r, "Could not set NDisc address");
4ff296b0
YW
411 link_enter_failed(link);
412 return 1;
413 } else if (r >= 0)
414 (void) manager_rtnl_process_address(rtnl, m, link->manager);
73854ba1 415
d98c546d
YW
416 if (link->ndisc_addresses_messages == 0) {
417 log_link_debug(link, "NDisc SLAAC addresses set.");
418 link->ndisc_addresses_configured = true;
69203fba 419
50550722 420 r = ndisc_remove_old(link);
69203fba
YW
421 if (r < 0) {
422 link_enter_failed(link);
423 return 1;
424 }
73854ba1
YW
425 }
426
427 return 1;
428}
429
50550722
YW
430static int ndisc_address_configure(Address *address, Link *link, sd_ndisc_router *rt) {
431 _cleanup_free_ NDiscAddress *na = NULL;
432 NDiscAddress *na_exist;
433 struct in6_addr router;
69203fba
YW
434 Address *ret;
435 int r;
436
437 assert(address);
438 assert(link);
50550722 439 assert(rt);
69203fba 440
37c0b601 441 r = address_configure(address, link, ndisc_address_handler, &ret);
69203fba
YW
442 if (r < 0)
443 return log_link_error_errno(link, r, "Failed to set NDisc SLAAC address: %m");
24b445c2
YW
444 if (r > 0)
445 link->ndisc_addresses_configured = false;
69203fba
YW
446
447 link->ndisc_addresses_messages++;
448
50550722 449 r = sd_ndisc_router_get_address(rt, &router);
69203fba 450 if (r < 0)
50550722
YW
451 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
452
453 na = new(NDiscAddress, 1);
454 if (!na)
455 return log_oom();
69203fba 456
50550722
YW
457 *na = (NDiscAddress) {
458 .router = router,
459 .address = ret,
460 };
461
462 na_exist = set_get(link->ndisc_addresses, na);
463 if (na_exist) {
464 na_exist->marked = false;
465 na_exist->router = router;
466 return 0;
467 }
468
469 r = set_ensure_put(&link->ndisc_addresses, &ndisc_address_hash_ops, na);
470 if (r < 0)
471 return log_link_error_errno(link, r, "Failed to store NDisc SLAAC address: %m");
472 assert(r > 0);
473 TAKE_PTR(na);
69203fba
YW
474
475 return 0;
476}
477
d5017c84 478static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
8e766630 479 _cleanup_(route_freep) Route *route = NULL;
b8ce3b44 480 struct in6_addr gateway;
1e7a0e21
LP
481 uint16_t lifetime;
482 unsigned preference;
c27abcf4 483 uint32_t table, mtu;
3b015d40 484 usec_t time_now;
13e8a49a 485 int r;
3b015d40 486
3b015d40 487 assert(link);
1e7a0e21 488 assert(rt);
3b015d40 489
1e7a0e21 490 r = sd_ndisc_router_get_lifetime(rt, &lifetime);
d5017c84 491 if (r < 0)
13e8a49a 492 return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
d5017c84 493
1e7a0e21 494 if (lifetime == 0) /* not a default router */
d5017c84 495 return 0;
1e7a0e21 496
b8ce3b44 497 r = sd_ndisc_router_get_address(rt, &gateway);
d5017c84 498 if (r < 0)
13e8a49a 499 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
1e7a0e21 500
b8ce3b44 501 if (link_has_ipv6_address(link, &gateway) > 0) {
5eec0a08
YW
502 if (DEBUG_LOGGING) {
503 _cleanup_free_ char *buffer = NULL;
6d7c7615 504
b8ce3b44 505 (void) in6_addr_to_string(&gateway, &buffer);
5eec0a08 506 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
b8ce3b44 507 strna(buffer));
6d7c7615 508 }
5eec0a08 509 return 0;
ce2ea782 510 }
6d7c7615 511
1e7a0e21 512 r = sd_ndisc_router_get_preference(rt, &preference);
d5017c84 513 if (r < 0)
13e8a49a 514 return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
1e7a0e21
LP
515
516 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
d5017c84 517 if (r < 0)
13e8a49a 518 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
1e7a0e21 519
d6fceaf1 520 r = sd_ndisc_router_get_mtu(rt, &mtu);
29b5ad08
JT
521 if (r == -ENODATA)
522 mtu = 0;
d5017c84 523 else if (r < 0)
13e8a49a 524 return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m");
d6fceaf1 525
c27abcf4
YW
526 table = link_get_ipv6_accept_ra_route_table(link);
527
1e7a0e21 528 r = route_new(&route);
d5017c84 529 if (r < 0)
13e8a49a 530 return log_oom();
1e7a0e21
LP
531
532 route->family = AF_INET6;
c27abcf4 533 route->table = table;
8ebafba9 534 route->priority = link->network->ipv6_accept_ra_route_metric;
1e7a0e21
LP
535 route->protocol = RTPROT_RA;
536 route->pref = preference;
6dd53981 537 route->gw_family = AF_INET6;
b8ce3b44 538 route->gw.in6 = gateway;
496db330 539 route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
d6fceaf1 540 route->mtu = mtu;
1e7a0e21 541
50550722 542 r = ndisc_route_configure(route, link, rt);
13e8a49a
YW
543 if (r < 0)
544 return log_link_error_errno(link, r, "Could not set default route: %m");
d5017c84 545
1985c54f 546 Route *route_gw;
2a54a044 547 HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
1a3a6309 548 if (!route_gw->gateway_from_dhcp_or_ra)
1985c54f
YW
549 continue;
550
5bb80a46 551 if (route_gw->gw_family != AF_INET6)
1985c54f
YW
552 continue;
553
b8ce3b44 554 route_gw->gw.in6 = gateway;
c27abcf4
YW
555 if (!route_gw->table_set)
556 route_gw->table = table;
557 if (!route_gw->priority_set)
8ebafba9 558 route_gw->priority = link->network->ipv6_accept_ra_route_metric;
c27abcf4
YW
559 if (!route_gw->protocol_set)
560 route_gw->protocol = RTPROT_RA;
561 if (!route_gw->pref_set)
086a351a 562 route_gw->pref = preference;
496db330 563 route_gw->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
c27abcf4
YW
564 if (route_gw->mtu == 0)
565 route_gw->mtu = mtu;
1985c54f 566
50550722 567 r = ndisc_route_configure(route_gw, link, rt);
13e8a49a
YW
568 if (r < 0)
569 return log_link_error_errno(link, r, "Could not set gateway: %m");
1985c54f
YW
570 }
571
d5017c84 572 return 0;
1e7a0e21
LP
573}
574
92ee90af
YW
575static bool stableprivate_address_is_valid(const struct in6_addr *addr) {
576 assert(addr);
577
578 /* According to rfc4291, generated address should not be in the following ranges. */
579
580 if (memcmp(addr, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291, SUBNET_ROUTER_ANYCAST_PREFIXLEN) == 0)
581 return false;
582
583 if (memcmp(addr, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN) == 0)
584 return false;
585
586 if (memcmp(addr, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291, RESERVED_SUBNET_ANYCAST_PREFIXLEN) == 0)
587 return false;
588
589 return true;
590}
591
592static int make_stableprivate_address(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, uint8_t dad_counter, struct in6_addr **ret) {
593 _cleanup_free_ struct in6_addr *addr = NULL;
594 sd_id128_t secret_key;
595 struct siphash state;
596 uint64_t rid;
597 size_t l;
598 int r;
599
600 /* According to rfc7217 section 5.1
601 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
602
603 r = sd_id128_get_machine_app_specific(NDISC_APP_ID, &secret_key);
604 if (r < 0)
605 return log_error_errno(r, "Failed to generate key: %m");
606
607 siphash24_init(&state, secret_key.bytes);
608
609 l = MAX(DIV_ROUND_UP(prefix_len, 8), 8);
610 siphash24_compress(prefix, l, &state);
611 siphash24_compress_string(link->ifname, &state);
b8162cd2
TR
612 /* Only last 8 bytes of IB MAC are stable */
613 if (link->iftype == ARPHRD_INFINIBAND)
614 siphash24_compress(&link->hw_addr.addr.infiniband[12], 8, &state);
615 else
616 siphash24_compress(link->hw_addr.addr.bytes, link->hw_addr.length, &state);
92ee90af
YW
617 siphash24_compress(&dad_counter, sizeof(uint8_t), &state);
618
619 rid = htole64(siphash24_finalize(&state));
620
621 addr = new(struct in6_addr, 1);
622 if (!addr)
623 return log_oom();
624
625 memcpy(addr->s6_addr, prefix->s6_addr, l);
626 memcpy(addr->s6_addr + l, &rid, 16 - l);
627
628 if (!stableprivate_address_is_valid(addr)) {
629 *ret = NULL;
630 return 0;
631 }
632
633 *ret = TAKE_PTR(addr);
634 return 1;
635}
636
637static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address, uint8_t prefixlen, Set **ret) {
c24c83dc 638 _cleanup_set_free_free_ Set *addresses = NULL;
5f506a55 639 IPv6Token *j;
5f506a55
SS
640 int r;
641
5f506a55 642 assert(link);
c24c83dc
KF
643 assert(address);
644 assert(ret);
645
92ee90af 646 addresses = set_new(&in6_addr_hash_ops);
c24c83dc
KF
647 if (!addresses)
648 return log_oom();
5f506a55 649
90e74a66 650 ORDERED_SET_FOREACH(j, link->network->ipv6_tokens) {
92ee90af 651 _cleanup_free_ struct in6_addr *new_address = NULL;
c24c83dc 652
5f506a55 653 if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
b8ce3b44 654 && (in6_addr_is_null(&j->prefix) || in6_addr_equal(&j->prefix, address))) {
0ddad04e 655 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
94876904
YW
656 * does not actually attempt Duplicate Address Detection; the counter will be incremented
657 * only when the address generation algorithm produces an invalid address, and the loop
658 * may exit with an address which ends up being unusable due to duplication on the link. */
5f506a55 659 for (; j->dad_counter < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; j->dad_counter++) {
b27caa34 660 r = make_stableprivate_address(link, address, prefixlen, j->dad_counter, &new_address);
5f506a55 661 if (r < 0)
92ee90af
YW
662 return r;
663 if (r > 0)
c24c83dc 664 break;
5f506a55 665 }
e2c4070e 666 } else if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC) {
92ee90af
YW
667 new_address = new(struct in6_addr, 1);
668 if (!new_address)
669 return log_oom();
5f506a55 670
92ee90af
YW
671 memcpy(new_address->s6_addr, address->s6_addr, 8);
672 memcpy(new_address->s6_addr + 8, j->prefix.s6_addr + 8, 8);
673 }
c24c83dc 674
92ee90af 675 if (new_address) {
c24c83dc
KF
676 r = set_put(addresses, new_address);
677 if (r < 0)
13e8a49a 678 return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
92ee90af
YW
679 else if (r == 0)
680 log_link_debug_errno(link, r, "Generated SLAAC address is duplicated, ignoring.");
681 else
682 TAKE_PTR(new_address);
c24c83dc
KF
683 }
684 }
685
686 /* fall back to EUI-64 if no tokens provided addresses */
687 if (set_isempty(addresses)) {
92ee90af 688 _cleanup_free_ struct in6_addr *new_address = NULL;
c24c83dc 689
92ee90af
YW
690 new_address = newdup(struct in6_addr, address, 1);
691 if (!new_address)
c24c83dc
KF
692 return log_oom();
693
92ee90af 694 r = generate_ipv6_eui_64_address(link, new_address);
a781ddef
SS
695 if (r < 0)
696 return log_link_error_errno(link, r, "Failed to generate EUI64 address: %m");
697
c24c83dc
KF
698 r = set_put(addresses, new_address);
699 if (r < 0)
13e8a49a 700 return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
92ee90af 701
c24c83dc 702 TAKE_PTR(new_address);
5f506a55
SS
703 }
704
c24c83dc 705 *ret = TAKE_PTR(addresses);
5f506a55
SS
706
707 return 0;
708}
c24c83dc 709
d5017c84 710static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
5f506a55 711 uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
c24c83dc 712 _cleanup_set_free_free_ Set *addresses = NULL;
8e766630 713 _cleanup_(address_freep) Address *address = NULL;
92ee90af 714 struct in6_addr addr, *a;
1e7a0e21 715 unsigned prefixlen;
5f506a55 716 usec_t time_now;
1e7a0e21
LP
717 int r;
718
719 assert(link);
720 assert(rt);
721
6554550f 722 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
d5017c84 723 if (r < 0)
13e8a49a 724 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
6554550f 725
1e7a0e21 726 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
d5017c84
YW
727 if (r < 0)
728 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
1e7a0e21
LP
729
730 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid);
d5017c84
YW
731 if (r < 0)
732 return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
1e7a0e21
LP
733
734 r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred);
d5017c84
YW
735 if (r < 0)
736 return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
3b015d40 737
92bdc3ff
SS
738 /* The preferred lifetime is never greater than the valid lifetime */
739 if (lifetime_preferred > lifetime_valid)
d5017c84 740 return 0;
92bdc3ff 741
92ee90af 742 r = sd_ndisc_router_prefix_get_address(rt, &addr);
d5017c84
YW
743 if (r < 0)
744 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
1e7a0e21 745
92ee90af 746 r = ndisc_router_generate_addresses(link, &addr, prefixlen, &addresses);
5f506a55 747 if (r < 0)
13e8a49a 748 return r;
c24c83dc 749
92ee90af
YW
750 r = address_new(&address);
751 if (r < 0)
752 return log_oom();
753
754 address->family = AF_INET6;
755 address->prefixlen = prefixlen;
756 address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
757 address->cinfo.ifa_prefered = lifetime_preferred;
758
90e74a66 759 SET_FOREACH(a, addresses) {
13e8a49a
YW
760 Address *existing_address;
761
fe841414
YW
762 address->in_addr.in6 = *a;
763
c24c83dc 764 /* see RFC4862 section 5.5.3.e */
fe841414 765 r = address_get(link, address, &existing_address);
c24c83dc
KF
766 if (r > 0) {
767 lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC;
768 if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining)
92ee90af 769 address->cinfo.ifa_valid = lifetime_valid;
c24c83dc 770 else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN)
92ee90af 771 address->cinfo.ifa_valid = lifetime_remaining;
c24c83dc 772 else
92ee90af 773 address->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN;
c24c83dc 774 } else if (lifetime_valid > 0)
92ee90af 775 address->cinfo.ifa_valid = lifetime_valid;
6554550f 776 else
01c344bd 777 continue; /* see RFC4862 section 5.5.3.d */
6554550f 778
92ee90af 779 if (address->cinfo.ifa_valid == 0)
c24c83dc 780 continue;
3b015d40 781
50550722 782 r = ndisc_address_configure(address, link, rt);
13e8a49a
YW
783 if (r < 0)
784 return log_link_error_errno(link, r, "Could not set SLAAC address: %m");
3b015d40 785 }
d5017c84
YW
786
787 return 0;
3b015d40
TG
788}
789
d5017c84 790static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
8e766630 791 _cleanup_(route_freep) Route *route = NULL;
3b015d40 792 usec_t time_now;
1e7a0e21
LP
793 uint32_t lifetime;
794 unsigned prefixlen;
3b015d40
TG
795 int r;
796
3b015d40 797 assert(link);
1e7a0e21 798 assert(rt);
3b015d40 799
1e7a0e21 800 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
d5017c84 801 if (r < 0)
13e8a49a 802 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
1e7a0e21
LP
803
804 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
d5017c84
YW
805 if (r < 0)
806 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
1e7a0e21
LP
807
808 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime);
d5017c84
YW
809 if (r < 0)
810 return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
3b015d40
TG
811
812 r = route_new(&route);
d5017c84 813 if (r < 0)
13e8a49a 814 return log_oom();
3b015d40 815
3b015d40 816 route->family = AF_INET6;
bdb9f580 817 route->table = link_get_ipv6_accept_ra_route_table(link);
8ebafba9 818 route->priority = link->network->ipv6_accept_ra_route_metric;
3b015d40
TG
819 route->protocol = RTPROT_RA;
820 route->flags = RTM_F_PREFIX;
3b015d40 821 route->dst_prefixlen = prefixlen;
496db330 822 route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
3b015d40 823
1e7a0e21 824 r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
d5017c84
YW
825 if (r < 0)
826 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
1e7a0e21 827
50550722 828 r = ndisc_route_configure(route, link, rt);
13e8a49a
YW
829 if (r < 0)
830 return log_link_error_errno(link, r, "Could not set prefix route: %m");;
d5017c84
YW
831
832 return 0;
3b015d40
TG
833}
834
d5017c84 835static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
8e766630 836 _cleanup_(route_freep) Route *route = NULL;
b8ce3b44 837 struct in6_addr gateway, dst;
1e7a0e21
LP
838 uint32_t lifetime;
839 unsigned preference, prefixlen;
fe307276 840 usec_t time_now;
7a695d8e 841 int r;
a13c50e7
TG
842
843 assert(link);
a13c50e7 844
1e7a0e21 845 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime);
d5017c84 846 if (r < 0)
13e8a49a 847 return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
d5017c84 848
1e7a0e21 849 if (lifetime == 0)
d5017c84 850 return 0;
a13c50e7 851
b8ce3b44 852 r = sd_ndisc_router_route_get_address(rt, &dst);
d5017c84 853 if (r < 0)
19e334bd 854 return log_link_error_errno(link, r, "Failed to get route address: %m");
3b015d40 855
de6b6ff8 856 if ((!set_isempty(link->network->ndisc_allow_listed_route_prefix) &&
b8ce3b44
YW
857 !set_contains(link->network->ndisc_allow_listed_route_prefix, &dst)) ||
858 set_contains(link->network->ndisc_deny_listed_route_prefix, &dst)) {
16c89e64
DP
859 if (DEBUG_LOGGING) {
860 _cleanup_free_ char *buf = NULL;
861
b8ce3b44 862 (void) in6_addr_to_string(&dst, &buf);
de6b6ff8 863 if (!set_isempty(link->network->ndisc_allow_listed_route_prefix))
b8ce3b44 864 log_link_debug(link, "Route prefix '%s' is not in allow list, ignoring", strna(buf));
de6b6ff8 865 else
b8ce3b44 866 log_link_debug(link, "Route prefix '%s' is in deny list, ignoring", strna(buf));
16c89e64
DP
867 }
868 return 0;
869 }
870
b8ce3b44 871 r = sd_ndisc_router_get_address(rt, &gateway);
19e334bd
YW
872 if (r < 0)
873 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
874
b8ce3b44 875 if (link_has_ipv6_address(link, &gateway) > 0) {
22101916 876 if (DEBUG_LOGGING) {
517fdd61
YW
877 _cleanup_free_ char *buf = NULL;
878
b8ce3b44
YW
879 (void) in6_addr_to_string(&gateway, &buf);
880 log_link_debug(link, "Advertised route gateway %s is local to the link, ignoring route", strna(buf));
22101916
DP
881 }
882 return 0;
883 }
884
1e7a0e21 885 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
d5017c84 886 if (r < 0)
13e8a49a 887 return log_link_error_errno(link, r, "Failed to get route prefix length: %m");
1e7a0e21
LP
888
889 r = sd_ndisc_router_route_get_preference(rt, &preference);
d5017c84 890 if (r < 0)
13e8a49a 891 return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
1e7a0e21
LP
892
893 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
d5017c84 894 if (r < 0)
13e8a49a 895 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
3b015d40
TG
896
897 r = route_new(&route);
d5017c84 898 if (r < 0)
13e8a49a 899 return log_oom();
3b015d40 900
3b015d40 901 route->family = AF_INET6;
bdb9f580 902 route->table = link_get_ipv6_accept_ra_route_table(link);
8ebafba9 903 route->priority = link->network->ipv6_accept_ra_route_metric;
3b015d40 904 route->protocol = RTPROT_RA;
1e7a0e21 905 route->pref = preference;
b8ce3b44 906 route->gw.in6 = gateway;
6dd53981 907 route->gw_family = AF_INET6;
b8ce3b44 908 route->dst.in6 = dst;
1e7a0e21 909 route->dst_prefixlen = prefixlen;
496db330 910 route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
3b015d40 911
50550722 912 r = ndisc_route_configure(route, link, rt);
13e8a49a
YW
913 if (r < 0)
914 return log_link_error_errno(link, r, "Could not set additional route: %m");
d5017c84
YW
915
916 return 0;
9d96e6c3 917}
a13c50e7 918
7a08d314 919static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
1e7a0e21
LP
920 siphash24_compress(&x->address, sizeof(x->address), state);
921}
922
7a08d314 923static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
1e7a0e21
LP
924 return memcmp(&a->address, &b->address, sizeof(a->address));
925}
926
b0b97766
YW
927DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
928 ndisc_rdnss_hash_ops,
929 NDiscRDNSS,
930 ndisc_rdnss_hash_func,
931 ndisc_rdnss_compare_func,
932 free);
1e7a0e21 933
d5017c84 934static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
1e7a0e21
LP
935 uint32_t lifetime;
936 const struct in6_addr *a;
50550722 937 struct in6_addr router;
b0b97766 938 NDiscRDNSS *rdnss;
1e7a0e21 939 usec_t time_now;
9092113d 940 bool updated = false;
13e8a49a 941 int n, r;
1e7a0e21
LP
942
943 assert(link);
944 assert(rt);
945
50550722
YW
946 r = sd_ndisc_router_get_address(rt, &router);
947 if (r < 0)
948 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
949
1e7a0e21 950 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
d5017c84 951 if (r < 0)
13e8a49a 952 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
1e7a0e21
LP
953
954 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime);
d5017c84 955 if (r < 0)
13e8a49a 956 return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
1e7a0e21
LP
957
958 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
d5017c84 959 if (n < 0)
13e8a49a 960 return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
1e7a0e21 961
90e74a66 962 SET_FOREACH(rdnss, link->ndisc_rdnss)
b8ce3b44 963 if (in6_addr_equal(&rdnss->router, &router))
50550722 964 rdnss->marked = true;
1e7a0e21 965
b0b97766
YW
966 if (lifetime == 0)
967 return 0;
1e7a0e21 968
b0b97766
YW
969 if (n >= (int) NDISC_RDNSS_MAX) {
970 log_link_warning(link, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX);
971 n = NDISC_RDNSS_MAX;
972 }
1e7a0e21 973
b0b97766
YW
974 for (int j = 0; j < n; j++) {
975 _cleanup_free_ NDiscRDNSS *x = NULL;
976 NDiscRDNSS d = {
977 .address = a[j],
978 };
1e7a0e21 979
b0b97766
YW
980 rdnss = set_get(link->ndisc_rdnss, &d);
981 if (rdnss) {
982 rdnss->marked = false;
50550722 983 rdnss->router = router;
b0b97766 984 rdnss->valid_until = time_now + lifetime * USEC_PER_SEC;
1e7a0e21
LP
985 continue;
986 }
987
d5017c84
YW
988 x = new(NDiscRDNSS, 1);
989 if (!x)
990 return log_oom();
1e7a0e21 991
d5017c84 992 *x = (NDiscRDNSS) {
b0b97766 993 .address = a[j],
50550722 994 .router = router,
d5017c84
YW
995 .valid_until = time_now + lifetime * USEC_PER_SEC,
996 };
1e7a0e21 997
35e601d4 998 r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
d5017c84
YW
999 if (r < 0)
1000 return log_oom();
1e7a0e21 1001 assert(r > 0);
9092113d
YW
1002
1003 updated = true;
1e7a0e21 1004 }
d5017c84 1005
9092113d
YW
1006 if (updated)
1007 link_dirty(link);
1008
d5017c84 1009 return 0;
1e7a0e21
LP
1010}
1011
7a08d314 1012static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
f281fc1e 1013 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x), state);
1e7a0e21
LP
1014}
1015
7a08d314 1016static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
1e7a0e21
LP
1017 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
1018}
1019
b0b97766
YW
1020DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1021 ndisc_dnssl_hash_ops,
1022 NDiscDNSSL,
1023 ndisc_dnssl_hash_func,
1024 ndisc_dnssl_compare_func,
1025 free);
1e7a0e21 1026
13e8a49a 1027static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
1e7a0e21 1028 _cleanup_strv_free_ char **l = NULL;
50550722 1029 struct in6_addr router;
1e7a0e21
LP
1030 uint32_t lifetime;
1031 usec_t time_now;
b0b97766 1032 NDiscDNSSL *dnssl;
9092113d 1033 bool updated = false;
b0b97766 1034 char **j;
1e7a0e21
LP
1035 int r;
1036
1037 assert(link);
1038 assert(rt);
1039
50550722
YW
1040 r = sd_ndisc_router_get_address(rt, &router);
1041 if (r < 0)
1042 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
1043
1e7a0e21 1044 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
13e8a49a
YW
1045 if (r < 0)
1046 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
1e7a0e21
LP
1047
1048 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime);
13e8a49a
YW
1049 if (r < 0)
1050 return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
1e7a0e21
LP
1051
1052 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
13e8a49a
YW
1053 if (r < 0)
1054 return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
1e7a0e21 1055
90e74a66 1056 SET_FOREACH(dnssl, link->ndisc_dnssl)
b8ce3b44 1057 if (in6_addr_equal(&dnssl->router, &router))
50550722 1058 dnssl->marked = true;
1e7a0e21 1059
b0b97766
YW
1060 if (lifetime == 0)
1061 return 0;
a34349e7 1062
b0b97766
YW
1063 if (strv_length(l) >= NDISC_DNSSL_MAX) {
1064 log_link_warning(link, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX);
1065 STRV_FOREACH(j, l + NDISC_DNSSL_MAX)
1066 *j = mfree(*j);
1067 }
1e7a0e21 1068
b0b97766
YW
1069 STRV_FOREACH(j, l) {
1070 _cleanup_free_ NDiscDNSSL *s = NULL;
1e7a0e21 1071
b0b97766
YW
1072 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1);
1073 if (!s)
1074 return log_oom();
1e7a0e21 1075
b0b97766 1076 strcpy(NDISC_DNSSL_DOMAIN(s), *j);
1e7a0e21 1077
b0b97766
YW
1078 dnssl = set_get(link->ndisc_dnssl, s);
1079 if (dnssl) {
1080 dnssl->marked = false;
50550722 1081 dnssl->router = router;
b0b97766 1082 dnssl->valid_until = time_now + lifetime * USEC_PER_SEC;
1e7a0e21
LP
1083 continue;
1084 }
1085
50550722 1086 s->router = router;
a34349e7 1087 s->valid_until = time_now + lifetime * USEC_PER_SEC;
1e7a0e21 1088
35e601d4 1089 r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
13e8a49a
YW
1090 if (r < 0)
1091 return log_oom();
1e7a0e21 1092 assert(r > 0);
9092113d
YW
1093
1094 updated = true;
1e7a0e21 1095 }
13e8a49a 1096
9092113d
YW
1097 if (updated)
1098 link_dirty(link);
1099
13e8a49a 1100 return 0;
1e7a0e21
LP
1101}
1102
e8c9b5b0 1103static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
1e7a0e21 1104 assert(link);
55d3fdcf 1105 assert(link->network);
1e7a0e21
LP
1106 assert(rt);
1107
13e8a49a 1108 for (int r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
1e7a0e21
LP
1109 uint8_t type;
1110
e8c9b5b0 1111 if (r < 0)
13e8a49a 1112 return log_link_error_errno(link, r, "Failed to iterate through options: %m");
1e7a0e21 1113 if (r == 0) /* EOF */
13e8a49a 1114 return 0;
1e7a0e21
LP
1115
1116 r = sd_ndisc_router_option_get_type(rt, &type);
e8c9b5b0 1117 if (r < 0)
13e8a49a 1118 return log_link_error_errno(link, r, "Failed to get RA option type: %m");
1e7a0e21
LP
1119
1120 switch (type) {
1121
1122 case SD_NDISC_OPTION_PREFIX_INFORMATION: {
b8ce3b44 1123 struct in6_addr a;
1e7a0e21
LP
1124 uint8_t flags;
1125
b8ce3b44 1126 r = sd_ndisc_router_prefix_get_address(rt, &a);
55d3fdcf
YW
1127 if (r < 0)
1128 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
1129
de6b6ff8 1130 if ((!set_isempty(link->network->ndisc_allow_listed_prefix) &&
b8ce3b44
YW
1131 !set_contains(link->network->ndisc_allow_listed_prefix, &a)) ||
1132 set_contains(link->network->ndisc_deny_listed_prefix, &a)) {
55d3fdcf
YW
1133 if (DEBUG_LOGGING) {
1134 _cleanup_free_ char *b = NULL;
1135
b8ce3b44 1136 (void) in6_addr_to_string(&a, &b);
de6b6ff8
SS
1137 if (!set_isempty(link->network->ndisc_allow_listed_prefix))
1138 log_link_debug(link, "Prefix '%s' is not in allow list, ignoring", strna(b));
1139 else
1140 log_link_debug(link, "Prefix '%s' is in deny list, ignoring", strna(b));
55d3fdcf 1141 }
55d3fdcf
YW
1142 break;
1143 }
1144
1e7a0e21 1145 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
e8c9b5b0 1146 if (r < 0)
13e8a49a 1147 return log_link_error_errno(link, r, "Failed to get RA prefix flags: %m");
1e7a0e21 1148
87d8a4de 1149 if (link->network->ipv6_accept_ra_use_onlink_prefix &&
13e8a49a
YW
1150 FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) {
1151 r = ndisc_router_process_onlink_prefix(link, rt);
1152 if (r < 0)
1153 return r;
1154 }
062c2eea 1155
87d8a4de 1156 if (link->network->ipv6_accept_ra_use_autonomous_prefix &&
13e8a49a
YW
1157 FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) {
1158 r = ndisc_router_process_autonomous_prefix(link, rt);
1159 if (r < 0)
1160 return r;
1161 }
1e7a0e21
LP
1162 break;
1163 }
1164
1165 case SD_NDISC_OPTION_ROUTE_INFORMATION:
13e8a49a
YW
1166 r = ndisc_router_process_route(link, rt);
1167 if (r < 0)
1168 return r;
1e7a0e21
LP
1169 break;
1170
1171 case SD_NDISC_OPTION_RDNSS:
13e8a49a
YW
1172 if (link->network->ipv6_accept_ra_use_dns) {
1173 r = ndisc_router_process_rdnss(link, rt);
1174 if (r < 0)
1175 return r;
1176 }
1e7a0e21
LP
1177 break;
1178
1179 case SD_NDISC_OPTION_DNSSL:
13e8a49a
YW
1180 if (link->network->ipv6_accept_ra_use_dns) {
1181 r = ndisc_router_process_dnssl(link, rt);
1182 if (r < 0)
1183 return r;
1184 }
1e7a0e21
LP
1185 break;
1186 }
1e7a0e21
LP
1187 }
1188}
1189
d5017c84 1190static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
b8ce3b44 1191 struct in6_addr router;
1e7a0e21 1192 uint64_t flags;
50550722
YW
1193 NDiscAddress *na;
1194 NDiscRoute *nr;
86e2be7b 1195 int r;
1e7a0e21
LP
1196
1197 assert(link);
1198 assert(link->network);
1199 assert(link->manager);
1200 assert(rt);
1201
b8ce3b44 1202 r = sd_ndisc_router_get_address(rt, &router);
75d26411
YW
1203 if (r < 0)
1204 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
1205
1206 if ((!set_isempty(link->network->ndisc_allow_listed_router) &&
b8ce3b44
YW
1207 !set_contains(link->network->ndisc_allow_listed_router, &router)) ||
1208 set_contains(link->network->ndisc_deny_listed_router, &router)) {
75d26411
YW
1209 if (DEBUG_LOGGING) {
1210 _cleanup_free_ char *buf = NULL;
1211
b8ce3b44 1212 (void) in6_addr_to_string(&router, &buf);
75d26411
YW
1213 if (!set_isempty(link->network->ndisc_allow_listed_router))
1214 log_link_debug(link, "Router '%s' is not in allow list, ignoring", strna(buf));
1215 else
1216 log_link_debug(link, "Router '%s' is in deny list, ignoring", strna(buf));
1217 }
1218 return 0;
1219 }
1220
90e74a66 1221 SET_FOREACH(na, link->ndisc_addresses)
b8ce3b44 1222 if (in6_addr_equal(&na->router, &router))
50550722
YW
1223 na->marked = true;
1224
90e74a66 1225 SET_FOREACH(nr, link->ndisc_routes)
b8ce3b44 1226 if (in6_addr_equal(&nr->router, &router))
50550722 1227 nr->marked = true;
69203fba 1228
1e7a0e21 1229 r = sd_ndisc_router_get_flags(rt, &flags);
d5017c84 1230 if (r < 0)
13e8a49a 1231 return log_link_error_errno(link, r, "Failed to get RA flags: %m");
1e7a0e21 1232
0e686fea
YW
1233 if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER) &&
1234 link->network->ipv6_accept_ra_start_dhcp6_client != IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO) ||
1235 link->network->ipv6_accept_ra_start_dhcp6_client == IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS) {
ac24e418 1236
0e686fea 1237 if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))
ac24e418
SS
1238 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
1239 r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED));
0e686fea
YW
1240 else
1241 /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode
1242 * even if router does not have M or O flag. */
1243 r = dhcp6_request_address(link, false);
1e7a0e21 1244 if (r < 0 && r != -EBUSY)
13e8a49a 1245 return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
69203fba 1246 else
1e7a0e21
LP
1247 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
1248 }
1249
13e8a49a
YW
1250 r = ndisc_router_process_default(link, rt);
1251 if (r < 0)
1252 return r;
1253 r = ndisc_router_process_options(link, rt);
1254 if (r < 0)
1255 return r;
d5017c84 1256
69203fba
YW
1257 if (link->ndisc_addresses_messages == 0)
1258 link->ndisc_addresses_configured = true;
92395e0e 1259 else
69203fba
YW
1260 log_link_debug(link, "Setting SLAAC addresses.");
1261
69203fba
YW
1262 if (link->ndisc_routes_messages == 0)
1263 link->ndisc_routes_configured = true;
1264 else
1265 log_link_debug(link, "Setting NDisc routes.");
1266
50550722 1267 r = ndisc_remove_old(link);
69203fba
YW
1268 if (r < 0)
1269 return r;
1270
1271 if (link->ndisc_addresses_configured && link->ndisc_routes_configured)
1272 link_check_ready(link);
1273 else
1274 link_set_state(link, LINK_STATE_CONFIGURING);
1275
1276 return 0;
1e7a0e21
LP
1277}
1278
2324fd3a 1279static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
9d96e6c3 1280 Link *link = userdata;
13e8a49a 1281 int r;
a13c50e7 1282
9d96e6c3 1283 assert(link);
a13c50e7 1284
9d96e6c3
TG
1285 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1286 return;
a13c50e7 1287
9d96e6c3 1288 switch (event) {
1e7a0e21
LP
1289
1290 case SD_NDISC_EVENT_ROUTER:
13e8a49a
YW
1291 r = ndisc_router_handler(link, rt);
1292 if (r < 0) {
1293 link_enter_failed(link);
1294 return;
1295 }
1e7a0e21
LP
1296 break;
1297
9d96e6c3 1298 case SD_NDISC_EVENT_TIMEOUT:
a8c10331 1299 log_link_debug(link, "NDisc handler get timeout event");
3336e946
YW
1300 if (link->ndisc_addresses_messages == 0 && link->ndisc_routes_messages == 0) {
1301 link->ndisc_addresses_configured = true;
1302 link->ndisc_routes_configured = true;
1303 link_check_ready(link);
1304 }
9d96e6c3
TG
1305 break;
1306 default:
a8c10331 1307 assert_not_reached("Unknown NDisc event");
a13c50e7
TG
1308 }
1309}
1310
1311int ndisc_configure(Link *link) {
1312 int r;
1313
1e7a0e21
LP
1314 assert(link);
1315
2ffd6d73
YW
1316 if (!link_ipv6_accept_ra_enabled(link))
1317 return 0;
a13c50e7 1318
5c078687 1319 if (link->ndisc)
bc9e40c9 1320 return -EBUSY; /* Already configured. */
2ffd6d73 1321
5c078687
YW
1322 r = sd_ndisc_new(&link->ndisc);
1323 if (r < 0)
1324 return r;
1325
1326 r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
1327 if (r < 0)
1328 return r;
a13c50e7 1329
b8162cd2 1330 r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.addr.ether);
a13c50e7
TG
1331 if (r < 0)
1332 return r;
1333
1e7a0e21 1334 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
a13c50e7
TG
1335 if (r < 0)
1336 return r;
1337
1e7a0e21 1338 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
a13c50e7
TG
1339 if (r < 0)
1340 return r;
1341
1e7a0e21
LP
1342 return 0;
1343}
1344
294f129b
YW
1345int ndisc_start(Link *link) {
1346 assert(link);
1347
1348 if (!link->ndisc || !link->dhcp6_client)
1349 return 0;
1350
1351 log_link_debug(link, "Discovering IPv6 routers");
1352
1353 return sd_ndisc_start(link->ndisc);
1354}
1355
1e7a0e21
LP
1356void ndisc_vacuum(Link *link) {
1357 NDiscRDNSS *r;
1358 NDiscDNSSL *d;
1e7a0e21
LP
1359 usec_t time_now;
1360
1361 assert(link);
1362
1363 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1364
1365 time_now = now(clock_boottime_or_monotonic());
1366
90e74a66 1367 SET_FOREACH(r, link->ndisc_rdnss)
9092113d 1368 if (r->valid_until < time_now)
02affb4e 1369 free(set_remove(link->ndisc_rdnss, r));
a13c50e7 1370
90e74a66 1371 SET_FOREACH(d, link->ndisc_dnssl)
9092113d 1372 if (d->valid_until < time_now)
02affb4e 1373 free(set_remove(link->ndisc_dnssl, d));
a13c50e7 1374}
c69305ff
LP
1375
1376void ndisc_flush(Link *link) {
1377 assert(link);
1378
1379 /* Removes all RDNSS and DNSSL entries, without exception */
1380
b0b97766
YW
1381 link->ndisc_rdnss = set_free(link->ndisc_rdnss);
1382 link->ndisc_dnssl = set_free(link->ndisc_dnssl);
c69305ff 1383}
e520ce64 1384
5f506a55
SS
1385int ipv6token_new(IPv6Token **ret) {
1386 IPv6Token *p;
1387
1388 p = new(IPv6Token, 1);
1389 if (!p)
1390 return -ENOMEM;
1391
1392 *p = (IPv6Token) {
1393 .address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_NONE,
1394 };
1395
1396 *ret = TAKE_PTR(p);
1397
1398 return 0;
1399}
1400
2c621495
YW
1401static void ipv6_token_hash_func(const IPv6Token *p, struct siphash *state) {
1402 siphash24_compress(&p->address_generation_type, sizeof(p->address_generation_type), state);
1403 siphash24_compress(&p->prefix, sizeof(p->prefix), state);
1404}
1405
1406static int ipv6_token_compare_func(const IPv6Token *a, const IPv6Token *b) {
1407 int r;
1408
1409 r = CMP(a->address_generation_type, b->address_generation_type);
1410 if (r != 0)
1411 return r;
1412
1413 return memcmp(&a->prefix, &b->prefix, sizeof(struct in6_addr));
1414}
1415
1416DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
5f506a55 1417 ipv6_token_hash_ops,
5f506a55 1418 IPv6Token,
2c621495
YW
1419 ipv6_token_hash_func,
1420 ipv6_token_compare_func,
5f506a55
SS
1421 free);
1422
de6b6ff8 1423int config_parse_ndisc_address_filter(
e520ce64
SS
1424 const char *unit,
1425 const char *filename,
1426 unsigned line,
1427 const char *section,
1428 unsigned section_line,
1429 const char *lvalue,
1430 int ltype,
1431 const char *rvalue,
1432 void *data,
1433 void *userdata) {
1434
16c89e64 1435 Set **list = data;
e520ce64
SS
1436 int r;
1437
1438 assert(filename);
1439 assert(lvalue);
1440 assert(rvalue);
1441 assert(data);
1442
1443 if (isempty(rvalue)) {
16c89e64 1444 *list = set_free_free(*list);
e520ce64
SS
1445 return 0;
1446 }
1447
16c89e64 1448 for (const char *p = rvalue;;) {
e520ce64
SS
1449 _cleanup_free_ char *n = NULL;
1450 _cleanup_free_ struct in6_addr *a = NULL;
1451 union in_addr_union ip;
1452
1453 r = extract_first_word(&p, &n, NULL, 0);
d96edb2c
YW
1454 if (r == -ENOMEM)
1455 return log_oom();
e520ce64 1456 if (r < 0) {
d96edb2c 1457 log_syntax(unit, LOG_WARNING, filename, line, r,
de6b6ff8
SS
1458 "Failed to parse NDisc %s=, ignoring assignment: %s",
1459 lvalue, rvalue);
e520ce64
SS
1460 return 0;
1461 }
1462 if (r == 0)
1463 return 0;
1464
1465 r = in_addr_from_string(AF_INET6, n, &ip);
1466 if (r < 0) {
d96edb2c 1467 log_syntax(unit, LOG_WARNING, filename, line, r,
de6b6ff8
SS
1468 "NDisc %s= entry is invalid, ignoring assignment: %s",
1469 lvalue, n);
e520ce64
SS
1470 continue;
1471 }
1472
e520ce64
SS
1473 a = newdup(struct in6_addr, &ip.in6, 1);
1474 if (!a)
1475 return log_oom();
1476
16c89e64 1477 r = set_ensure_consume(list, &in6_addr_hash_ops, TAKE_PTR(a));
35e601d4
ZJS
1478 if (r < 0)
1479 return log_oom();
16c89e64
DP
1480 if (r == 0)
1481 log_syntax(unit, LOG_WARNING, filename, line, 0,
de6b6ff8
SS
1482 "NDisc %s= entry is duplicated, ignoring assignment: %s",
1483 lvalue, n);
e520ce64 1484 }
e520ce64 1485}
5f506a55
SS
1486
1487int config_parse_address_generation_type(
1488 const char *unit,
1489 const char *filename,
1490 unsigned line,
1491 const char *section,
1492 unsigned section_line,
1493 const char *lvalue,
1494 int ltype,
1495 const char *rvalue,
1496 void *data,
1497 void *userdata) {
1498
1499 _cleanup_free_ IPv6Token *token = NULL;
5f506a55
SS
1500 union in_addr_union buffer;
1501 Network *network = data;
1502 const char *p;
1503 int r;
1504
1505 assert(filename);
1506 assert(lvalue);
1507 assert(rvalue);
1508 assert(data);
1509
1510 if (isempty(rvalue)) {
2c621495 1511 network->ipv6_tokens = ordered_set_free(network->ipv6_tokens);
5f506a55
SS
1512 return 0;
1513 }
1514
5f506a55
SS
1515 r = ipv6token_new(&token);
1516 if (r < 0)
1517 return log_oom();
1518
b27caa34 1519 if ((p = startswith(rvalue, "prefixstable"))) {
5f506a55 1520 token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE;
b27caa34
YW
1521 if (*p == ':')
1522 p++;
1523 else if (*p == '\0')
1524 p = NULL;
1525 else {
1526 log_syntax(unit, LOG_WARNING, filename, line, 0,
1527 "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
1528 lvalue, rvalue);
1529 return 0;
1530 }
1531 } else {
e2c4070e 1532 token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC;
b27caa34
YW
1533 p = startswith(rvalue, "static:");
1534 if (!p)
1535 p = rvalue;
f0c1ad30
YW
1536 }
1537
b27caa34
YW
1538 if (p) {
1539 r = in_addr_from_string(AF_INET6, p, &buffer);
1540 if (r < 0) {
1541 log_syntax(unit, LOG_WARNING, filename, line, r,
1542 "Failed to parse IP address in %s=, ignoring assignment: %s",
1543 lvalue, rvalue);
1544 return 0;
1545 }
1546 if (token->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC &&
1547 in_addr_is_null(AF_INET6, &buffer)) {
1548 log_syntax(unit, LOG_WARNING, filename, line, 0,
1549 "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
1550 lvalue, rvalue);
1551 return 0;
1552 }
1553 token->prefix = buffer.in6;
5f506a55
SS
1554 }
1555
9b1fd1f5
SS
1556 r = ordered_set_ensure_put(&network->ipv6_tokens, &ipv6_token_hash_ops, token);
1557 if (r == -ENOMEM)
5f506a55 1558 return log_oom();
2c621495
YW
1559 if (r == -EEXIST)
1560 log_syntax(unit, LOG_DEBUG, filename, line, r,
1561 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue);
1562 else if (r < 0)
d96edb2c 1563 log_syntax(unit, LOG_WARNING, filename, line, r,
2c621495
YW
1564 "Failed to store IPv6 token '%s', ignoring: %m", rvalue);
1565 else
1566 TAKE_PTR(token);
5f506a55
SS
1567
1568 return 0;
1569}
ac24e418 1570
f225a338
YW
1571DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains, dhcp_use_domains, DHCPUseDomains,
1572 "Failed to parse UseDomains= setting");
ac24e418 1573DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
f225a338 1574 "Failed to parse DHCPv6Client= setting");
ac24e418
SS
1575static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1576 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1577 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1578 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1579};
1580
1581DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);