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