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