]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
ac5b242fc1535c6c7ddf52553df256f8e0ccd9ae
[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 Address *address;
153 Iterator i;
154
155 assert(link);
156 assert(rt);
157
158 r = sd_ndisc_router_get_lifetime(rt, &lifetime);
159 if (r < 0)
160 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
161
162 if (lifetime == 0) /* not a default router */
163 return 0;
164
165 r = sd_ndisc_router_get_address(rt, &gateway.in6);
166 if (r < 0)
167 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
168
169 SET_FOREACH(address, link->addresses, i) {
170 if (address->family != AF_INET6)
171 continue;
172 if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) {
173 _cleanup_free_ char *buffer = NULL;
174
175 (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer);
176 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
177 strnull(buffer));
178 return 0;
179 }
180 }
181
182 SET_FOREACH(address, link->addresses_foreign, i) {
183 if (address->family != AF_INET6)
184 continue;
185 if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) {
186 _cleanup_free_ char *buffer = NULL;
187
188 (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer);
189 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
190 strnull(buffer));
191 return 0;
192 }
193 }
194
195 r = sd_ndisc_router_get_preference(rt, &preference);
196 if (r < 0)
197 return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
198
199 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
200 if (r < 0)
201 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
202
203 r = sd_ndisc_router_get_mtu(rt, &mtu);
204 if (r == -ENODATA)
205 mtu = 0;
206 else if (r < 0)
207 return log_link_warning_errno(link, r, "Failed to get default router MTU from RA: %m");
208
209 r = route_new(&route);
210 if (r < 0)
211 return log_link_error_errno(link, r, "Could not allocate route: %m");
212
213 route->family = AF_INET6;
214 route->table = link_get_ipv6_accept_ra_route_table(link);
215 route->priority = link->network->dhcp6_route_metric;
216 route->protocol = RTPROT_RA;
217 route->pref = preference;
218 route->gw = gateway;
219 route->lifetime = time_now + lifetime * USEC_PER_SEC;
220 route->mtu = mtu;
221
222 r = route_configure(route, link, ndisc_route_handler);
223 if (r < 0) {
224 log_link_warning_errno(link, r, "Could not set default route: %m");
225 link_enter_failed(link);
226 return r;
227 }
228 if (r > 0)
229 link->ndisc_routes_messages++;
230
231 Route *route_gw;
232 LIST_FOREACH(routes, route_gw, link->network->static_routes) {
233 if (!route_gw->gateway_from_dhcp)
234 continue;
235
236 if (route_gw->family != AF_INET6)
237 continue;
238
239 route_gw->gw = gateway;
240
241 r = route_configure(route_gw, link, ndisc_route_handler);
242 if (r < 0) {
243 log_link_error_errno(link, r, "Could not set gateway: %m");
244 link_enter_failed(link);
245 return r;
246 }
247 if (r > 0)
248 link->ndisc_routes_messages++;
249 }
250
251 return 0;
252 }
253
254 static int ndisc_router_generate_addresses(Link *link, unsigned prefixlen, uint32_t lifetime_preferred, Address *address, Set **ret) {
255 _cleanup_set_free_free_ Set *addresses = NULL;
256 struct in6_addr addr;
257 IPv6Token *j;
258 Iterator i;
259 int r;
260
261 assert(link);
262 assert(address);
263 assert(ret);
264
265 addresses = set_new(&address_hash_ops);
266 if (!addresses)
267 return log_oom();
268
269 addr = address->in_addr.in6;
270 ORDERED_HASHMAP_FOREACH(j, link->network->ipv6_tokens, i) {
271 bool have_address = false;
272 _cleanup_(address_freep) Address *new_address = NULL;
273
274 r = address_new(&new_address);
275 if (r < 0)
276 return log_oom();
277
278 *new_address = *address;
279
280 if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
281 && memcmp(&j->prefix, &addr, FAMILY_ADDRESS_SIZE(address->family)) == 0) {
282 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
283 does not actually attempt Duplicate Address Detection; the counter will be incremented
284 only when the address generation algorithm produces an invalid address, and the loop
285 may exit with an address which ends up being unusable due to duplication on the link.
286 */
287 for (; j->dad_counter < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; j->dad_counter++) {
288 r = make_stableprivate_address(link, &j->prefix, prefixlen, j->dad_counter, &new_address->in_addr.in6);
289 if (r < 0)
290 break;
291
292 if (stableprivate_address_is_valid(&new_address->in_addr.in6)) {
293 have_address = true;
294 break;
295 }
296 }
297 } else if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC) {
298 memcpy(new_address->in_addr.in6.s6_addr + 8, j->prefix.s6_addr + 8, 8);
299 have_address = true;
300 }
301
302 if (have_address) {
303 new_address->prefixlen = prefixlen;
304 new_address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
305 new_address->cinfo.ifa_prefered = lifetime_preferred;
306
307 r = set_put(addresses, new_address);
308 if (r < 0)
309 return log_link_warning_errno(link, r, "Failed to store address: %m");
310 TAKE_PTR(new_address);
311 }
312 }
313
314 /* fall back to EUI-64 if no tokens provided addresses */
315 if (set_isempty(addresses)) {
316 _cleanup_(address_freep) Address *new_address = NULL;
317
318 r = address_new(&new_address);
319 if (r < 0)
320 return log_oom();
321
322 *new_address = *address;
323
324 r = generate_ipv6_eui_64_address(link, &new_address->in_addr.in6);
325 if (r < 0)
326 return log_link_error_errno(link, r, "Failed to generate EUI64 address: %m");
327
328 new_address->prefixlen = prefixlen;
329 new_address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
330 new_address->cinfo.ifa_prefered = lifetime_preferred;
331
332 r = set_put(addresses, new_address);
333 if (r < 0)
334 return log_link_warning_errno(link, r, "Failed to store address: %m");
335 TAKE_PTR(new_address);
336 }
337
338 *ret = TAKE_PTR(addresses);
339
340 return 0;
341 }
342
343 static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
344 uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
345 _cleanup_set_free_free_ Set *addresses = NULL;
346 _cleanup_(address_freep) Address *address = NULL;
347 unsigned prefixlen;
348 usec_t time_now;
349 Address *existing_address, *a;
350 Iterator i;
351 int r;
352
353 assert(link);
354 assert(rt);
355
356 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
357 if (r < 0)
358 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
359
360 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
361 if (r < 0)
362 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
363
364 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid);
365 if (r < 0)
366 return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
367
368 r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred);
369 if (r < 0)
370 return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
371
372 /* The preferred lifetime is never greater than the valid lifetime */
373 if (lifetime_preferred > lifetime_valid)
374 return 0;
375
376 r = address_new(&address);
377 if (r < 0)
378 return log_link_error_errno(link, r, "Could not allocate address: %m");
379
380 address->family = AF_INET6;
381 r = sd_ndisc_router_prefix_get_address(rt, &address->in_addr.in6);
382 if (r < 0)
383 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
384
385 r = ndisc_router_generate_addresses(link, prefixlen, lifetime_preferred, address, &addresses);
386 if (r < 0)
387 return log_link_error_errno(link, r, "Failed to generate SLAAC addresses: %m");
388
389 SET_FOREACH(a, addresses, i) {
390 /* see RFC4862 section 5.5.3.e */
391 r = address_get(link, a->family, &a->in_addr, a->prefixlen, &existing_address);
392 if (r > 0) {
393 lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC;
394 if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining)
395 a->cinfo.ifa_valid = lifetime_valid;
396 else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN)
397 a->cinfo.ifa_valid = lifetime_remaining;
398 else
399 a->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN;
400 } else if (lifetime_valid > 0)
401 a->cinfo.ifa_valid = lifetime_valid;
402 else
403 continue; /* see RFC4862 section 5.5.3.d */
404
405 if (a->cinfo.ifa_valid == 0)
406 continue;
407
408 r = address_configure(a, link, ndisc_address_handler, true);
409 if (r < 0) {
410 log_link_warning_errno(link, r, "Could not set SLAAC address: %m");
411 link_enter_failed(link);
412 return r;
413 }
414 if (r > 0)
415 link->ndisc_addresses_messages++;
416 }
417
418 return 0;
419 }
420
421 static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
422 _cleanup_(route_freep) Route *route = NULL;
423 usec_t time_now;
424 uint32_t lifetime;
425 unsigned prefixlen;
426 int r;
427
428 assert(link);
429 assert(rt);
430
431 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
432 if (r < 0)
433 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
434
435 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
436 if (r < 0)
437 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
438
439 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime);
440 if (r < 0)
441 return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
442
443 r = route_new(&route);
444 if (r < 0)
445 return log_link_error_errno(link, r, "Could not allocate route: %m");
446
447 route->family = AF_INET6;
448 route->table = link_get_ipv6_accept_ra_route_table(link);
449 route->priority = link->network->dhcp6_route_metric;
450 route->protocol = RTPROT_RA;
451 route->flags = RTM_F_PREFIX;
452 route->dst_prefixlen = prefixlen;
453 route->lifetime = time_now + lifetime * USEC_PER_SEC;
454
455 r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
456 if (r < 0)
457 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
458
459 r = route_configure(route, link, ndisc_route_handler);
460 if (r < 0) {
461 log_link_warning_errno(link, r, "Could not set prefix route: %m");
462 link_enter_failed(link);
463 return r;
464 }
465 if (r > 0)
466 link->ndisc_routes_messages++;
467
468 return 0;
469 }
470
471 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
472 _cleanup_(route_freep) Route *route = NULL;
473 struct in6_addr gateway;
474 uint32_t lifetime;
475 unsigned preference, prefixlen;
476 usec_t time_now;
477 int r;
478
479 assert(link);
480
481 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime);
482 if (r < 0)
483 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
484
485 if (lifetime == 0)
486 return 0;
487
488 r = sd_ndisc_router_get_address(rt, &gateway);
489 if (r < 0)
490 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
491
492 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
493 if (r < 0)
494 return log_link_warning_errno(link, r, "Failed to get route prefix length: %m");
495
496 r = sd_ndisc_router_route_get_preference(rt, &preference);
497 if (r < 0)
498 return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
499
500 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
501 if (r < 0)
502 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
503
504 r = route_new(&route);
505 if (r < 0)
506 return log_link_error_errno(link, r, "Could not allocate route: %m");
507
508 route->family = AF_INET6;
509 route->table = link_get_ipv6_accept_ra_route_table(link);
510 route->priority = link->network->dhcp6_route_metric;
511 route->protocol = RTPROT_RA;
512 route->pref = preference;
513 route->gw.in6 = gateway;
514 route->dst_prefixlen = prefixlen;
515 route->lifetime = time_now + lifetime * USEC_PER_SEC;
516
517 r = sd_ndisc_router_route_get_address(rt, &route->dst.in6);
518 if (r < 0)
519 return log_link_error_errno(link, r, "Failed to get route address: %m");
520
521 r = route_configure(route, link, ndisc_route_handler);
522 if (r < 0) {
523 log_link_warning_errno(link, r, "Could not set additional route: %m");
524 link_enter_failed(link);
525 return r;
526 }
527 if (r > 0)
528 link->ndisc_routes_messages++;
529
530 return 0;
531 }
532
533 static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
534 siphash24_compress(&x->address, sizeof(x->address), state);
535 }
536
537 static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
538 return memcmp(&a->address, &b->address, sizeof(a->address));
539 }
540
541 DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops, NDiscRDNSS, ndisc_rdnss_hash_func, ndisc_rdnss_compare_func);
542
543 static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
544 uint32_t lifetime;
545 const struct in6_addr *a;
546 usec_t time_now;
547 int i, n, r;
548
549 assert(link);
550 assert(rt);
551
552 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
553 if (r < 0)
554 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
555
556 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime);
557 if (r < 0)
558 return log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
559
560 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
561 if (n < 0)
562 return log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m");
563
564 for (i = 0; i < n; i++) {
565 _cleanup_free_ NDiscRDNSS *x = NULL;
566 NDiscRDNSS d = {
567 .address = a[i],
568 }, *y;
569
570 if (lifetime == 0) {
571 (void) set_remove(link->ndisc_rdnss, &d);
572 link_dirty(link);
573 continue;
574 }
575
576 y = set_get(link->ndisc_rdnss, &d);
577 if (y) {
578 y->valid_until = time_now + lifetime * USEC_PER_SEC;
579 continue;
580 }
581
582 ndisc_vacuum(link);
583
584 if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX) {
585 log_link_warning(link, "Too many RDNSS records per link, ignoring.");
586 continue;
587 }
588
589 x = new(NDiscRDNSS, 1);
590 if (!x)
591 return log_oom();
592
593 *x = (NDiscRDNSS) {
594 .address = a[i],
595 .valid_until = time_now + lifetime * USEC_PER_SEC,
596 };
597
598 r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
599 if (r < 0)
600 return log_oom();
601 assert(r > 0);
602
603 link_dirty(link);
604 }
605
606 return 0;
607 }
608
609 static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
610 siphash24_compress(NDISC_DNSSL_DOMAIN(x), strlen(NDISC_DNSSL_DOMAIN(x)), state);
611 }
612
613 static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
614 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
615 }
616
617 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops, NDiscDNSSL, ndisc_dnssl_hash_func, ndisc_dnssl_compare_func);
618
619 static void ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
620 _cleanup_strv_free_ char **l = NULL;
621 uint32_t lifetime;
622 usec_t time_now;
623 char **i;
624 int r;
625
626 assert(link);
627 assert(rt);
628
629 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
630 if (r < 0) {
631 log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
632 return;
633 }
634
635 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime);
636 if (r < 0) {
637 log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
638 return;
639 }
640
641 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
642 if (r < 0) {
643 log_link_warning_errno(link, r, "Failed to get RDNSS addresses: %m");
644 return;
645 }
646
647 STRV_FOREACH(i, l) {
648 _cleanup_free_ NDiscDNSSL *s;
649 NDiscDNSSL *x;
650
651 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*i) + 1);
652 if (!s) {
653 log_oom();
654 return;
655 }
656
657 strcpy(NDISC_DNSSL_DOMAIN(s), *i);
658
659 if (lifetime == 0) {
660 (void) set_remove(link->ndisc_dnssl, s);
661 link_dirty(link);
662 continue;
663 }
664
665 x = set_get(link->ndisc_dnssl, s);
666 if (x) {
667 x->valid_until = time_now + lifetime * USEC_PER_SEC;
668 continue;
669 }
670
671 ndisc_vacuum(link);
672
673 if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX) {
674 log_link_warning(link, "Too many DNSSL records per link, ignoring.");
675 continue;
676 }
677
678 s->valid_until = time_now + lifetime * USEC_PER_SEC;
679
680 r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
681 if (r < 0) {
682 log_oom();
683 return;
684 }
685 assert(r > 0);
686
687 link_dirty(link);
688 }
689 }
690
691 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
692 int r;
693
694 assert(link);
695 assert(link->network);
696 assert(rt);
697
698 r = sd_ndisc_router_option_rewind(rt);
699 for (;;) {
700 uint8_t type;
701
702 if (r < 0)
703 return log_link_warning_errno(link, r, "Failed to iterate through options: %m");
704 if (r == 0) /* EOF */
705 break;
706
707 r = sd_ndisc_router_option_get_type(rt, &type);
708 if (r < 0)
709 return log_link_warning_errno(link, r, "Failed to get RA option type: %m");
710
711 switch (type) {
712
713 case SD_NDISC_OPTION_PREFIX_INFORMATION: {
714 union in_addr_union a;
715 uint8_t flags;
716
717 r = sd_ndisc_router_prefix_get_address(rt, &a.in6);
718 if (r < 0)
719 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
720
721 if (set_contains(link->network->ndisc_deny_listed_prefix, &a.in6)) {
722 if (DEBUG_LOGGING) {
723 _cleanup_free_ char *b = NULL;
724
725 (void) in_addr_to_string(AF_INET6, &a, &b);
726 log_link_debug(link, "Prefix '%s' is deny-listed, ignoring", strna(b));
727 }
728
729 break;
730 }
731
732 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
733 if (r < 0)
734 return log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m");
735
736 if (link->network->ipv6_accept_ra_use_onlink_prefix &&
737 FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK))
738 (void) ndisc_router_process_onlink_prefix(link, rt);
739
740 if (link->network->ipv6_accept_ra_use_autonomous_prefix &&
741 FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO))
742 (void) ndisc_router_process_autonomous_prefix(link, rt);
743
744 break;
745 }
746
747 case SD_NDISC_OPTION_ROUTE_INFORMATION:
748 (void) ndisc_router_process_route(link, rt);
749 break;
750
751 case SD_NDISC_OPTION_RDNSS:
752 if (link->network->ipv6_accept_ra_use_dns)
753 (void) ndisc_router_process_rdnss(link, rt);
754 break;
755
756 case SD_NDISC_OPTION_DNSSL:
757 if (link->network->ipv6_accept_ra_use_dns)
758 (void) ndisc_router_process_dnssl(link, rt);
759 break;
760 }
761
762 r = sd_ndisc_router_option_next(rt);
763 }
764
765 return 0;
766 }
767
768 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
769 uint64_t flags;
770 int r;
771
772 assert(link);
773 assert(link->network);
774 assert(link->manager);
775 assert(rt);
776
777 r = sd_ndisc_router_get_flags(rt, &flags);
778 if (r < 0)
779 return log_link_warning_errno(link, r, "Failed to get RA flags: %m");
780
781 if ((flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER) && link->network->ipv6_accept_ra_start_dhcp6_client)) {
782
783 if (link->network->ipv6_accept_ra_start_dhcp6_client == IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS)
784 r = dhcp6_request_address(link, false);
785 else
786 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
787 r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED));
788
789 if (r < 0 && r != -EBUSY)
790 log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
791 else {
792 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
793 r = 0;
794 }
795 }
796
797 (void) ndisc_router_process_default(link, rt);
798 (void) ndisc_router_process_options(link, rt);
799
800 return r;
801 }
802
803 static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
804 Link *link = userdata;
805
806 assert(link);
807
808 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
809 return;
810
811 switch (event) {
812
813 case SD_NDISC_EVENT_ROUTER:
814 link->ndisc_addresses_configured = false;
815 link->ndisc_routes_configured = false;
816
817 (void) ndisc_router_handler(link, rt);
818
819 if (link->ndisc_addresses_messages == 0)
820 link->ndisc_addresses_configured = true;
821 else
822 log_link_debug(link, "Setting SLAAC addresses.");
823
824 if (link->ndisc_routes_messages == 0)
825 link->ndisc_routes_configured = true;
826 else
827 log_link_debug(link, "Setting NDisc routes.");
828
829 if (link->ndisc_addresses_configured && link->ndisc_routes_configured)
830 link_check_ready(link);
831 else
832 link_set_state(link, LINK_STATE_CONFIGURING);
833 break;
834
835 case SD_NDISC_EVENT_TIMEOUT:
836 log_link_debug(link, "NDISC handler get timeout event");
837 link->ndisc_addresses_configured = true;
838 link->ndisc_routes_configured = true;
839 link_check_ready(link);
840
841 break;
842 default:
843 log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
844 }
845 }
846
847 int ndisc_configure(Link *link) {
848 int r;
849
850 assert(link);
851
852 r = sd_ndisc_new(&link->ndisc);
853 if (r < 0)
854 return r;
855
856 r = sd_ndisc_attach_event(link->ndisc, NULL, 0);
857 if (r < 0)
858 return r;
859
860 r = sd_ndisc_set_mac(link->ndisc, &link->mac);
861 if (r < 0)
862 return r;
863
864 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
865 if (r < 0)
866 return r;
867
868 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
869 if (r < 0)
870 return r;
871
872 return 0;
873 }
874
875 void ndisc_vacuum(Link *link) {
876 NDiscRDNSS *r;
877 NDiscDNSSL *d;
878 Iterator i;
879 usec_t time_now;
880
881 assert(link);
882
883 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
884
885 time_now = now(clock_boottime_or_monotonic());
886
887 SET_FOREACH(r, link->ndisc_rdnss, i)
888 if (r->valid_until < time_now) {
889 free(set_remove(link->ndisc_rdnss, r));
890 link_dirty(link);
891 }
892
893 SET_FOREACH(d, link->ndisc_dnssl, i)
894 if (d->valid_until < time_now) {
895 free(set_remove(link->ndisc_dnssl, d));
896 link_dirty(link);
897 }
898 }
899
900 void ndisc_flush(Link *link) {
901 assert(link);
902
903 /* Removes all RDNSS and DNSSL entries, without exception */
904
905 link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
906 link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
907 }
908
909 int ipv6token_new(IPv6Token **ret) {
910 IPv6Token *p;
911
912 p = new(IPv6Token, 1);
913 if (!p)
914 return -ENOMEM;
915
916 *p = (IPv6Token) {
917 .address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_NONE,
918 };
919
920 *ret = TAKE_PTR(p);
921
922 return 0;
923 }
924
925 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
926 ipv6_token_hash_ops,
927 void,
928 trivial_hash_func,
929 trivial_compare_func,
930 IPv6Token,
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 < 0) {
966 log_syntax(unit, LOG_ERR, filename, line, r,
967 "Failed to parse NDISC deny-listed prefix, ignoring assignment: %s",
968 rvalue);
969 return 0;
970 }
971 if (r == 0)
972 return 0;
973
974 r = in_addr_from_string(AF_INET6, n, &ip);
975 if (r < 0) {
976 log_syntax(unit, LOG_ERR, filename, line, r,
977 "NDISC deny-listed prefix is invalid, ignoring assignment: %s", n);
978 continue;
979 }
980
981 if (set_contains(network->ndisc_deny_listed_prefix, &ip.in6))
982 continue;
983
984 a = newdup(struct in6_addr, &ip.in6, 1);
985 if (!a)
986 return log_oom();
987
988 r = set_ensure_consume(&network->ndisc_deny_listed_prefix, &in6_addr_hash_ops, TAKE_PTR(a));
989 if (r < 0)
990 return log_oom();
991 }
992
993 return 0;
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_hashmap_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_ERR, 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_ERR, 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_hashmap_ensure_allocated(&network->ipv6_tokens, &ipv6_token_hash_ops);
1053 if (r < 0)
1054 return log_oom();
1055
1056 r = ordered_hashmap_put(network->ipv6_tokens, &token->prefix, token);
1057 if (r < 0) {
1058 log_syntax(unit, LOG_ERR, filename, line, r,
1059 "Failed to store IPv6 token '%s'", rvalue);
1060 return 0;
1061 }
1062
1063 TAKE_PTR(token);
1064
1065 return 0;
1066 }
1067
1068 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
1069 "Failed to parse DHCPv6Client= setting")
1070 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1071 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1072 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1073 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1074 };
1075
1076 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);