]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
Merge pull request #17238 from keszybz/man-tmp-noexec
[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, 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 = gateway;
517 route->lifetime = time_now + lifetime * USEC_PER_SEC;
518 route->mtu = mtu;
519
520 r = ndisc_route_configure(route, link, rt);
521 if (r < 0)
522 return log_link_error_errno(link, r, "Could not set default route: %m");
523
524 Route *route_gw;
525 HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
526 if (!route_gw->gateway_from_dhcp)
527 continue;
528
529 if (route_gw->family != AF_INET6)
530 continue;
531
532 route_gw->gw = gateway;
533
534 r = ndisc_route_configure(route_gw, link, rt);
535 if (r < 0)
536 return log_link_error_errno(link, r, "Could not set gateway: %m");
537 }
538
539 return 0;
540 }
541
542 static bool stableprivate_address_is_valid(const struct in6_addr *addr) {
543 assert(addr);
544
545 /* According to rfc4291, generated address should not be in the following ranges. */
546
547 if (memcmp(addr, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291, SUBNET_ROUTER_ANYCAST_PREFIXLEN) == 0)
548 return false;
549
550 if (memcmp(addr, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN) == 0)
551 return false;
552
553 if (memcmp(addr, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291, RESERVED_SUBNET_ANYCAST_PREFIXLEN) == 0)
554 return false;
555
556 return true;
557 }
558
559 static int make_stableprivate_address(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, uint8_t dad_counter, struct in6_addr **ret) {
560 _cleanup_free_ struct in6_addr *addr = NULL;
561 sd_id128_t secret_key;
562 struct siphash state;
563 uint64_t rid;
564 size_t l;
565 int r;
566
567 /* According to rfc7217 section 5.1
568 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
569
570 r = sd_id128_get_machine_app_specific(NDISC_APP_ID, &secret_key);
571 if (r < 0)
572 return log_error_errno(r, "Failed to generate key: %m");
573
574 siphash24_init(&state, secret_key.bytes);
575
576 l = MAX(DIV_ROUND_UP(prefix_len, 8), 8);
577 siphash24_compress(prefix, l, &state);
578 siphash24_compress_string(link->ifname, &state);
579 siphash24_compress(&link->mac, sizeof(struct ether_addr), &state);
580 siphash24_compress(&dad_counter, sizeof(uint8_t), &state);
581
582 rid = htole64(siphash24_finalize(&state));
583
584 addr = new(struct in6_addr, 1);
585 if (!addr)
586 return log_oom();
587
588 memcpy(addr->s6_addr, prefix->s6_addr, l);
589 memcpy(addr->s6_addr + l, &rid, 16 - l);
590
591 if (!stableprivate_address_is_valid(addr)) {
592 *ret = NULL;
593 return 0;
594 }
595
596 *ret = TAKE_PTR(addr);
597 return 1;
598 }
599
600 static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address, uint8_t prefixlen, Set **ret) {
601 _cleanup_set_free_free_ Set *addresses = NULL;
602 IPv6Token *j;
603 int r;
604
605 assert(link);
606 assert(address);
607 assert(ret);
608
609 addresses = set_new(&in6_addr_hash_ops);
610 if (!addresses)
611 return log_oom();
612
613 ORDERED_SET_FOREACH(j, link->network->ipv6_tokens) {
614 _cleanup_free_ struct in6_addr *new_address = NULL;
615
616 if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
617 && (IN6_IS_ADDR_UNSPECIFIED(&j->prefix) || IN6_ARE_ADDR_EQUAL(&j->prefix, address))) {
618 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
619 does not actually attempt Duplicate Address Detection; the counter will be incremented
620 only when the address generation algorithm produces an invalid address, and the loop
621 may exit with an address which ends up being unusable due to duplication on the link.
622 */
623 for (; j->dad_counter < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; j->dad_counter++) {
624 r = make_stableprivate_address(link, address, prefixlen, j->dad_counter, &new_address);
625 if (r < 0)
626 return r;
627 if (r > 0)
628 break;
629 }
630 } else if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC) {
631 new_address = new(struct in6_addr, 1);
632 if (!new_address)
633 return log_oom();
634
635 memcpy(new_address->s6_addr, address->s6_addr, 8);
636 memcpy(new_address->s6_addr + 8, j->prefix.s6_addr + 8, 8);
637 }
638
639 if (new_address) {
640 r = set_put(addresses, new_address);
641 if (r < 0)
642 return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
643 else if (r == 0)
644 log_link_debug_errno(link, r, "Generated SLAAC address is duplicated, ignoring.");
645 else
646 TAKE_PTR(new_address);
647 }
648 }
649
650 /* fall back to EUI-64 if no tokens provided addresses */
651 if (set_isempty(addresses)) {
652 _cleanup_free_ struct in6_addr *new_address = NULL;
653
654 new_address = newdup(struct in6_addr, address, 1);
655 if (!new_address)
656 return log_oom();
657
658 r = generate_ipv6_eui_64_address(link, new_address);
659 if (r < 0)
660 return log_link_error_errno(link, r, "Failed to generate EUI64 address: %m");
661
662 r = set_put(addresses, new_address);
663 if (r < 0)
664 return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
665
666 TAKE_PTR(new_address);
667 }
668
669 *ret = TAKE_PTR(addresses);
670
671 return 0;
672 }
673
674 static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
675 uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
676 _cleanup_set_free_free_ Set *addresses = NULL;
677 _cleanup_(address_freep) Address *address = NULL;
678 struct in6_addr addr, *a;
679 unsigned prefixlen;
680 usec_t time_now;
681 int r;
682
683 assert(link);
684 assert(rt);
685
686 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
687 if (r < 0)
688 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
689
690 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
691 if (r < 0)
692 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
693
694 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid);
695 if (r < 0)
696 return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
697
698 r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred);
699 if (r < 0)
700 return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
701
702 /* The preferred lifetime is never greater than the valid lifetime */
703 if (lifetime_preferred > lifetime_valid)
704 return 0;
705
706 r = sd_ndisc_router_prefix_get_address(rt, &addr);
707 if (r < 0)
708 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
709
710 r = ndisc_router_generate_addresses(link, &addr, prefixlen, &addresses);
711 if (r < 0)
712 return r;
713
714 r = address_new(&address);
715 if (r < 0)
716 return log_oom();
717
718 address->family = AF_INET6;
719 address->prefixlen = prefixlen;
720 address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
721 address->cinfo.ifa_prefered = lifetime_preferred;
722
723 SET_FOREACH(a, addresses) {
724 Address *existing_address;
725
726 /* see RFC4862 section 5.5.3.e */
727 r = address_get(link, AF_INET6, (union in_addr_union *) a, prefixlen, &existing_address);
728 if (r > 0) {
729 lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC;
730 if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining)
731 address->cinfo.ifa_valid = lifetime_valid;
732 else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN)
733 address->cinfo.ifa_valid = lifetime_remaining;
734 else
735 address->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN;
736 } else if (lifetime_valid > 0)
737 address->cinfo.ifa_valid = lifetime_valid;
738 else
739 continue; /* see RFC4862 section 5.5.3.d */
740
741 if (address->cinfo.ifa_valid == 0)
742 continue;
743
744 address->in_addr.in6 = *a;
745
746 r = ndisc_address_configure(address, link, rt);
747 if (r < 0)
748 return log_link_error_errno(link, r, "Could not set SLAAC address: %m");
749 }
750
751 return 0;
752 }
753
754 static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
755 _cleanup_(route_freep) Route *route = NULL;
756 usec_t time_now;
757 uint32_t lifetime;
758 unsigned prefixlen;
759 int r;
760
761 assert(link);
762 assert(rt);
763
764 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
765 if (r < 0)
766 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
767
768 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
769 if (r < 0)
770 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
771
772 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime);
773 if (r < 0)
774 return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
775
776 r = route_new(&route);
777 if (r < 0)
778 return log_oom();
779
780 route->family = AF_INET6;
781 route->table = link_get_ipv6_accept_ra_route_table(link);
782 route->priority = link->network->dhcp6_route_metric;
783 route->protocol = RTPROT_RA;
784 route->flags = RTM_F_PREFIX;
785 route->dst_prefixlen = prefixlen;
786 route->lifetime = time_now + lifetime * USEC_PER_SEC;
787
788 r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
789 if (r < 0)
790 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
791
792 r = ndisc_route_configure(route, link, rt);
793 if (r < 0)
794 return log_link_error_errno(link, r, "Could not set prefix route: %m");;
795
796 return 0;
797 }
798
799 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
800 _cleanup_(route_freep) Route *route = NULL;
801 struct in6_addr gateway;
802 uint32_t lifetime;
803 unsigned preference, prefixlen;
804 usec_t time_now;
805 int r;
806
807 assert(link);
808
809 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime);
810 if (r < 0)
811 return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
812
813 if (lifetime == 0)
814 return 0;
815
816 r = sd_ndisc_router_get_address(rt, &gateway);
817 if (r < 0)
818 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
819
820 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
821 if (r < 0)
822 return log_link_error_errno(link, r, "Failed to get route prefix length: %m");
823
824 r = sd_ndisc_router_route_get_preference(rt, &preference);
825 if (r < 0)
826 return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
827
828 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
829 if (r < 0)
830 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
831
832 r = route_new(&route);
833 if (r < 0)
834 return log_oom();
835
836 route->family = AF_INET6;
837 route->table = link_get_ipv6_accept_ra_route_table(link);
838 route->priority = link->network->dhcp6_route_metric;
839 route->protocol = RTPROT_RA;
840 route->pref = preference;
841 route->gw.in6 = gateway;
842 route->dst_prefixlen = prefixlen;
843 route->lifetime = time_now + lifetime * USEC_PER_SEC;
844
845 r = sd_ndisc_router_route_get_address(rt, &route->dst.in6);
846 if (r < 0)
847 return log_link_error_errno(link, r, "Failed to get route address: %m");
848
849 r = ndisc_route_configure(route, link, rt);
850 if (r < 0)
851 return log_link_error_errno(link, r, "Could not set additional route: %m");
852
853 return 0;
854 }
855
856 static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
857 siphash24_compress(&x->address, sizeof(x->address), state);
858 }
859
860 static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
861 return memcmp(&a->address, &b->address, sizeof(a->address));
862 }
863
864 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
865 ndisc_rdnss_hash_ops,
866 NDiscRDNSS,
867 ndisc_rdnss_hash_func,
868 ndisc_rdnss_compare_func,
869 free);
870
871 static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
872 uint32_t lifetime;
873 const struct in6_addr *a;
874 struct in6_addr router;
875 NDiscRDNSS *rdnss;
876 usec_t time_now;
877 int n, r;
878
879 assert(link);
880 assert(rt);
881
882 r = sd_ndisc_router_get_address(rt, &router);
883 if (r < 0)
884 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
885
886 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
887 if (r < 0)
888 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
889
890 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime);
891 if (r < 0)
892 return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
893
894 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
895 if (n < 0)
896 return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
897
898 SET_FOREACH(rdnss, link->ndisc_rdnss)
899 if (IN6_ARE_ADDR_EQUAL(&rdnss->router, &router))
900 rdnss->marked = true;
901
902 if (lifetime == 0)
903 return 0;
904
905 if (n >= (int) NDISC_RDNSS_MAX) {
906 log_link_warning(link, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX);
907 n = NDISC_RDNSS_MAX;
908 }
909
910 for (int j = 0; j < n; j++) {
911 _cleanup_free_ NDiscRDNSS *x = NULL;
912 NDiscRDNSS d = {
913 .address = a[j],
914 };
915
916 rdnss = set_get(link->ndisc_rdnss, &d);
917 if (rdnss) {
918 rdnss->marked = false;
919 rdnss->router = router;
920 rdnss->valid_until = time_now + lifetime * USEC_PER_SEC;
921 continue;
922 }
923
924 x = new(NDiscRDNSS, 1);
925 if (!x)
926 return log_oom();
927
928 *x = (NDiscRDNSS) {
929 .address = a[j],
930 .router = router,
931 .valid_until = time_now + lifetime * USEC_PER_SEC,
932 };
933
934 r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
935 if (r < 0)
936 return log_oom();
937 assert(r > 0);
938 }
939
940 return 0;
941 }
942
943 static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
944 siphash24_compress_string(NDISC_DNSSL_DOMAIN(x), state);
945 }
946
947 static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
948 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
949 }
950
951 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
952 ndisc_dnssl_hash_ops,
953 NDiscDNSSL,
954 ndisc_dnssl_hash_func,
955 ndisc_dnssl_compare_func,
956 free);
957
958 static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
959 _cleanup_strv_free_ char **l = NULL;
960 struct in6_addr router;
961 uint32_t lifetime;
962 usec_t time_now;
963 NDiscDNSSL *dnssl;
964 char **j;
965 int r;
966
967 assert(link);
968 assert(rt);
969
970 r = sd_ndisc_router_get_address(rt, &router);
971 if (r < 0)
972 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
973
974 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
975 if (r < 0)
976 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
977
978 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime);
979 if (r < 0)
980 return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
981
982 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
983 if (r < 0)
984 return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
985
986 SET_FOREACH(dnssl, link->ndisc_dnssl)
987 if (IN6_ARE_ADDR_EQUAL(&dnssl->router, &router))
988 dnssl->marked = true;
989
990 if (lifetime == 0)
991 return 0;
992
993 if (strv_length(l) >= NDISC_DNSSL_MAX) {
994 log_link_warning(link, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX);
995 STRV_FOREACH(j, l + NDISC_DNSSL_MAX)
996 *j = mfree(*j);
997 }
998
999 STRV_FOREACH(j, l) {
1000 _cleanup_free_ NDiscDNSSL *s = NULL;
1001
1002 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1);
1003 if (!s)
1004 return log_oom();
1005
1006 strcpy(NDISC_DNSSL_DOMAIN(s), *j);
1007
1008 dnssl = set_get(link->ndisc_dnssl, s);
1009 if (dnssl) {
1010 dnssl->marked = false;
1011 dnssl->router = router;
1012 dnssl->valid_until = time_now + lifetime * USEC_PER_SEC;
1013 continue;
1014 }
1015
1016 s->router = router;
1017 s->valid_until = time_now + lifetime * USEC_PER_SEC;
1018
1019 r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
1020 if (r < 0)
1021 return log_oom();
1022 assert(r > 0);
1023 }
1024
1025 return 0;
1026 }
1027
1028 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
1029 assert(link);
1030 assert(link->network);
1031 assert(rt);
1032
1033 for (int r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
1034 uint8_t type;
1035
1036 if (r < 0)
1037 return log_link_error_errno(link, r, "Failed to iterate through options: %m");
1038 if (r == 0) /* EOF */
1039 return 0;
1040
1041 r = sd_ndisc_router_option_get_type(rt, &type);
1042 if (r < 0)
1043 return log_link_error_errno(link, r, "Failed to get RA option type: %m");
1044
1045 switch (type) {
1046
1047 case SD_NDISC_OPTION_PREFIX_INFORMATION: {
1048 union in_addr_union a;
1049 uint8_t flags;
1050
1051 r = sd_ndisc_router_prefix_get_address(rt, &a.in6);
1052 if (r < 0)
1053 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
1054
1055 if (set_contains(link->network->ndisc_deny_listed_prefix, &a.in6)) {
1056 if (DEBUG_LOGGING) {
1057 _cleanup_free_ char *b = NULL;
1058
1059 (void) in_addr_to_string(AF_INET6, &a, &b);
1060 log_link_debug(link, "Prefix '%s' is deny-listed, ignoring", strna(b));
1061 }
1062 break;
1063 }
1064
1065 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
1066 if (r < 0)
1067 return log_link_error_errno(link, r, "Failed to get RA prefix flags: %m");
1068
1069 if (link->network->ipv6_accept_ra_use_onlink_prefix &&
1070 FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) {
1071 r = ndisc_router_process_onlink_prefix(link, rt);
1072 if (r < 0)
1073 return r;
1074 }
1075
1076 if (link->network->ipv6_accept_ra_use_autonomous_prefix &&
1077 FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) {
1078 r = ndisc_router_process_autonomous_prefix(link, rt);
1079 if (r < 0)
1080 return r;
1081 }
1082 break;
1083 }
1084
1085 case SD_NDISC_OPTION_ROUTE_INFORMATION:
1086 r = ndisc_router_process_route(link, rt);
1087 if (r < 0)
1088 return r;
1089 break;
1090
1091 case SD_NDISC_OPTION_RDNSS:
1092 if (link->network->ipv6_accept_ra_use_dns) {
1093 r = ndisc_router_process_rdnss(link, rt);
1094 if (r < 0)
1095 return r;
1096 }
1097 break;
1098
1099 case SD_NDISC_OPTION_DNSSL:
1100 if (link->network->ipv6_accept_ra_use_dns) {
1101 r = ndisc_router_process_dnssl(link, rt);
1102 if (r < 0)
1103 return r;
1104 }
1105 break;
1106 }
1107 }
1108 }
1109
1110 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
1111 struct in6_addr router;
1112 uint64_t flags;
1113 NDiscAddress *na;
1114 NDiscRoute *nr;
1115 int r;
1116
1117 assert(link);
1118 assert(link->network);
1119 assert(link->manager);
1120 assert(rt);
1121
1122 link->ndisc_addresses_configured = false;
1123 link->ndisc_routes_configured = false;
1124
1125 link_dirty(link);
1126
1127 r = sd_ndisc_router_get_address(rt, &router);
1128 if (r < 0)
1129 return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
1130
1131 SET_FOREACH(na, link->ndisc_addresses)
1132 if (IN6_ARE_ADDR_EQUAL(&na->router, &router))
1133 na->marked = true;
1134
1135 SET_FOREACH(nr, link->ndisc_routes)
1136 if (IN6_ARE_ADDR_EQUAL(&nr->router, &router))
1137 nr->marked = true;
1138
1139 r = sd_ndisc_router_get_flags(rt, &flags);
1140 if (r < 0)
1141 return log_link_error_errno(link, r, "Failed to get RA flags: %m");
1142
1143 if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER) && link->network->ipv6_accept_ra_start_dhcp6_client)) {
1144
1145 if (link->network->ipv6_accept_ra_start_dhcp6_client == IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS)
1146 r = dhcp6_request_address(link, false);
1147 else
1148 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
1149 r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED));
1150 if (r < 0 && r != -EBUSY)
1151 return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
1152 else
1153 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
1154 }
1155
1156 r = ndisc_router_process_default(link, rt);
1157 if (r < 0)
1158 return r;
1159 r = ndisc_router_process_options(link, rt);
1160 if (r < 0)
1161 return r;
1162
1163 if (link->ndisc_addresses_messages == 0)
1164 link->ndisc_addresses_configured = true;
1165 else {
1166 log_link_debug(link, "Setting SLAAC addresses.");
1167
1168 /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are
1169 * called, the related flags must be cleared. Otherwise, the link becomes configured
1170 * state before routes are configured. */
1171 link->static_routes_configured = false;
1172 link->static_nexthops_configured = false;
1173 }
1174
1175 if (link->ndisc_routes_messages == 0)
1176 link->ndisc_routes_configured = true;
1177 else
1178 log_link_debug(link, "Setting NDisc routes.");
1179
1180 r = ndisc_remove_old(link);
1181 if (r < 0)
1182 return r;
1183
1184 if (link->ndisc_addresses_configured && link->ndisc_routes_configured)
1185 link_check_ready(link);
1186 else
1187 link_set_state(link, LINK_STATE_CONFIGURING);
1188
1189 return 0;
1190 }
1191
1192 static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
1193 Link *link = userdata;
1194 int r;
1195
1196 assert(link);
1197
1198 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1199 return;
1200
1201 switch (event) {
1202
1203 case SD_NDISC_EVENT_ROUTER:
1204 r = ndisc_router_handler(link, rt);
1205 if (r < 0) {
1206 link_enter_failed(link);
1207 return;
1208 }
1209 break;
1210
1211 case SD_NDISC_EVENT_TIMEOUT:
1212 log_link_debug(link, "NDisc handler get timeout event");
1213 if (link->ndisc_addresses_messages == 0 && link->ndisc_routes_messages == 0) {
1214 link->ndisc_addresses_configured = true;
1215 link->ndisc_routes_configured = true;
1216 link_check_ready(link);
1217 }
1218 break;
1219 default:
1220 assert_not_reached("Unknown NDisc event");
1221 }
1222 }
1223
1224 int ndisc_configure(Link *link) {
1225 int r;
1226
1227 assert(link);
1228
1229 if (!link_ipv6_accept_ra_enabled(link))
1230 return 0;
1231
1232 if (!link->ndisc) {
1233 r = sd_ndisc_new(&link->ndisc);
1234 if (r < 0)
1235 return r;
1236
1237 r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
1238 if (r < 0)
1239 return r;
1240 }
1241
1242 r = sd_ndisc_set_mac(link->ndisc, &link->mac);
1243 if (r < 0)
1244 return r;
1245
1246 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
1247 if (r < 0)
1248 return r;
1249
1250 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
1251 if (r < 0)
1252 return r;
1253
1254 return 0;
1255 }
1256
1257 void ndisc_vacuum(Link *link) {
1258 NDiscRDNSS *r;
1259 NDiscDNSSL *d;
1260 usec_t time_now;
1261 bool updated = false;
1262
1263 assert(link);
1264
1265 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
1266
1267 time_now = now(clock_boottime_or_monotonic());
1268
1269 SET_FOREACH(r, link->ndisc_rdnss)
1270 if (r->valid_until < time_now) {
1271 free(set_remove(link->ndisc_rdnss, r));
1272 updated = true;
1273 }
1274
1275 SET_FOREACH(d, link->ndisc_dnssl)
1276 if (d->valid_until < time_now) {
1277 free(set_remove(link->ndisc_dnssl, d));
1278 updated = true;
1279 }
1280
1281 if (updated)
1282 link_dirty(link);
1283 }
1284
1285 void ndisc_flush(Link *link) {
1286 assert(link);
1287
1288 /* Removes all RDNSS and DNSSL entries, without exception */
1289
1290 link->ndisc_rdnss = set_free(link->ndisc_rdnss);
1291 link->ndisc_dnssl = set_free(link->ndisc_dnssl);
1292 }
1293
1294 int ipv6token_new(IPv6Token **ret) {
1295 IPv6Token *p;
1296
1297 p = new(IPv6Token, 1);
1298 if (!p)
1299 return -ENOMEM;
1300
1301 *p = (IPv6Token) {
1302 .address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_NONE,
1303 };
1304
1305 *ret = TAKE_PTR(p);
1306
1307 return 0;
1308 }
1309
1310 static void ipv6_token_hash_func(const IPv6Token *p, struct siphash *state) {
1311 siphash24_compress(&p->address_generation_type, sizeof(p->address_generation_type), state);
1312 siphash24_compress(&p->prefix, sizeof(p->prefix), state);
1313 }
1314
1315 static int ipv6_token_compare_func(const IPv6Token *a, const IPv6Token *b) {
1316 int r;
1317
1318 r = CMP(a->address_generation_type, b->address_generation_type);
1319 if (r != 0)
1320 return r;
1321
1322 return memcmp(&a->prefix, &b->prefix, sizeof(struct in6_addr));
1323 }
1324
1325 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1326 ipv6_token_hash_ops,
1327 IPv6Token,
1328 ipv6_token_hash_func,
1329 ipv6_token_compare_func,
1330 free);
1331
1332 int config_parse_ndisc_deny_listed_prefix(
1333 const char *unit,
1334 const char *filename,
1335 unsigned line,
1336 const char *section,
1337 unsigned section_line,
1338 const char *lvalue,
1339 int ltype,
1340 const char *rvalue,
1341 void *data,
1342 void *userdata) {
1343
1344 Network *network = data;
1345 const char *p;
1346 int r;
1347
1348 assert(filename);
1349 assert(lvalue);
1350 assert(rvalue);
1351 assert(data);
1352
1353 if (isempty(rvalue)) {
1354 network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix);
1355 return 0;
1356 }
1357
1358 for (p = rvalue;;) {
1359 _cleanup_free_ char *n = NULL;
1360 _cleanup_free_ struct in6_addr *a = NULL;
1361 union in_addr_union ip;
1362
1363 r = extract_first_word(&p, &n, NULL, 0);
1364 if (r == -ENOMEM)
1365 return log_oom();
1366 if (r < 0) {
1367 log_syntax(unit, LOG_WARNING, filename, line, r,
1368 "Failed to parse NDisc deny-listed prefix, ignoring assignment: %s",
1369 rvalue);
1370 return 0;
1371 }
1372 if (r == 0)
1373 return 0;
1374
1375 r = in_addr_from_string(AF_INET6, n, &ip);
1376 if (r < 0) {
1377 log_syntax(unit, LOG_WARNING, filename, line, r,
1378 "NDisc deny-listed prefix is invalid, ignoring assignment: %s", n);
1379 continue;
1380 }
1381
1382 if (set_contains(network->ndisc_deny_listed_prefix, &ip.in6))
1383 continue;
1384
1385 a = newdup(struct in6_addr, &ip.in6, 1);
1386 if (!a)
1387 return log_oom();
1388
1389 r = set_ensure_consume(&network->ndisc_deny_listed_prefix, &in6_addr_hash_ops, TAKE_PTR(a));
1390 if (r < 0)
1391 return log_oom();
1392 }
1393 }
1394
1395 int config_parse_address_generation_type(
1396 const char *unit,
1397 const char *filename,
1398 unsigned line,
1399 const char *section,
1400 unsigned section_line,
1401 const char *lvalue,
1402 int ltype,
1403 const char *rvalue,
1404 void *data,
1405 void *userdata) {
1406
1407 _cleanup_free_ IPv6Token *token = NULL;
1408 union in_addr_union buffer;
1409 Network *network = data;
1410 const char *p;
1411 int r;
1412
1413 assert(filename);
1414 assert(lvalue);
1415 assert(rvalue);
1416 assert(data);
1417
1418 if (isempty(rvalue)) {
1419 network->ipv6_tokens = ordered_set_free(network->ipv6_tokens);
1420 return 0;
1421 }
1422
1423 r = ipv6token_new(&token);
1424 if (r < 0)
1425 return log_oom();
1426
1427 if ((p = startswith(rvalue, "prefixstable"))) {
1428 token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE;
1429 if (*p == ':')
1430 p++;
1431 else if (*p == '\0')
1432 p = NULL;
1433 else {
1434 log_syntax(unit, LOG_WARNING, filename, line, 0,
1435 "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
1436 lvalue, rvalue);
1437 return 0;
1438 }
1439 } else {
1440 token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC;
1441 p = startswith(rvalue, "static:");
1442 if (!p)
1443 p = rvalue;
1444 }
1445
1446 if (p) {
1447 r = in_addr_from_string(AF_INET6, p, &buffer);
1448 if (r < 0) {
1449 log_syntax(unit, LOG_WARNING, filename, line, r,
1450 "Failed to parse IP address in %s=, ignoring assignment: %s",
1451 lvalue, rvalue);
1452 return 0;
1453 }
1454 if (token->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC &&
1455 in_addr_is_null(AF_INET6, &buffer)) {
1456 log_syntax(unit, LOG_WARNING, filename, line, 0,
1457 "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
1458 lvalue, rvalue);
1459 return 0;
1460 }
1461 token->prefix = buffer.in6;
1462 }
1463
1464 r = ordered_set_ensure_allocated(&network->ipv6_tokens, &ipv6_token_hash_ops);
1465 if (r < 0)
1466 return log_oom();
1467
1468 r = ordered_set_put(network->ipv6_tokens, token);
1469 if (r == -EEXIST)
1470 log_syntax(unit, LOG_DEBUG, filename, line, r,
1471 "IPv6 token '%s' is duplicated, ignoring: %m", rvalue);
1472 else if (r < 0)
1473 log_syntax(unit, LOG_WARNING, filename, line, r,
1474 "Failed to store IPv6 token '%s', ignoring: %m", rvalue);
1475 else
1476 TAKE_PTR(token);
1477
1478 return 0;
1479 }
1480
1481 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
1482 "Failed to parse DHCPv6Client= setting")
1483 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1484 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1485 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1486 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1487 };
1488
1489 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);