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