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