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