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