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