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