]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
network: make link_request_set_nexthop() called from link_request_set_routes() or...
[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 /* address_handler calls link_request_set_routes() and link_request_set_nexthop().
825 * Before they are called, the related flags must be cleared. Otherwise, the link
826 * becomes configured state before routes are configured. */
827 link->static_routes_configured = false;
828 link->static_nexthops_configured = false;
829 }
830
831 if (link->ndisc_routes_messages == 0)
832 link->ndisc_routes_configured = true;
833 else
834 log_link_debug(link, "Setting NDisc routes.");
835
836 if (link->ndisc_addresses_configured && link->ndisc_routes_configured)
837 link_check_ready(link);
838 else
839 link_set_state(link, LINK_STATE_CONFIGURING);
840 break;
841
842 case SD_NDISC_EVENT_TIMEOUT:
843 log_link_debug(link, "NDISC handler get timeout event");
844 link->ndisc_addresses_configured = true;
845 link->ndisc_routes_configured = true;
846 link_check_ready(link);
847
848 break;
849 default:
850 log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
851 }
852 }
853
854 int ndisc_configure(Link *link) {
855 int r;
856
857 assert(link);
858
859 r = sd_ndisc_new(&link->ndisc);
860 if (r < 0)
861 return r;
862
863 r = sd_ndisc_attach_event(link->ndisc, NULL, 0);
864 if (r < 0)
865 return r;
866
867 r = sd_ndisc_set_mac(link->ndisc, &link->mac);
868 if (r < 0)
869 return r;
870
871 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
872 if (r < 0)
873 return r;
874
875 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
876 if (r < 0)
877 return r;
878
879 return 0;
880 }
881
882 void ndisc_vacuum(Link *link) {
883 NDiscRDNSS *r;
884 NDiscDNSSL *d;
885 Iterator i;
886 usec_t time_now;
887
888 assert(link);
889
890 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
891
892 time_now = now(clock_boottime_or_monotonic());
893
894 SET_FOREACH(r, link->ndisc_rdnss, i)
895 if (r->valid_until < time_now) {
896 free(set_remove(link->ndisc_rdnss, r));
897 link_dirty(link);
898 }
899
900 SET_FOREACH(d, link->ndisc_dnssl, i)
901 if (d->valid_until < time_now) {
902 free(set_remove(link->ndisc_dnssl, d));
903 link_dirty(link);
904 }
905 }
906
907 void ndisc_flush(Link *link) {
908 assert(link);
909
910 /* Removes all RDNSS and DNSSL entries, without exception */
911
912 link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
913 link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
914 }
915
916 int ipv6token_new(IPv6Token **ret) {
917 IPv6Token *p;
918
919 p = new(IPv6Token, 1);
920 if (!p)
921 return -ENOMEM;
922
923 *p = (IPv6Token) {
924 .address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_NONE,
925 };
926
927 *ret = TAKE_PTR(p);
928
929 return 0;
930 }
931
932 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
933 ipv6_token_hash_ops,
934 void,
935 trivial_hash_func,
936 trivial_compare_func,
937 IPv6Token,
938 free);
939
940 int config_parse_ndisc_deny_listed_prefix(
941 const char *unit,
942 const char *filename,
943 unsigned line,
944 const char *section,
945 unsigned section_line,
946 const char *lvalue,
947 int ltype,
948 const char *rvalue,
949 void *data,
950 void *userdata) {
951
952 Network *network = data;
953 const char *p;
954 int r;
955
956 assert(filename);
957 assert(lvalue);
958 assert(rvalue);
959 assert(data);
960
961 if (isempty(rvalue)) {
962 network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix);
963 return 0;
964 }
965
966 for (p = rvalue;;) {
967 _cleanup_free_ char *n = NULL;
968 _cleanup_free_ struct in6_addr *a = NULL;
969 union in_addr_union ip;
970
971 r = extract_first_word(&p, &n, NULL, 0);
972 if (r < 0) {
973 log_syntax(unit, LOG_ERR, filename, line, r,
974 "Failed to parse NDISC deny-listed prefix, ignoring assignment: %s",
975 rvalue);
976 return 0;
977 }
978 if (r == 0)
979 return 0;
980
981 r = in_addr_from_string(AF_INET6, n, &ip);
982 if (r < 0) {
983 log_syntax(unit, LOG_ERR, filename, line, r,
984 "NDISC deny-listed prefix is invalid, ignoring assignment: %s", n);
985 continue;
986 }
987
988 if (set_contains(network->ndisc_deny_listed_prefix, &ip.in6))
989 continue;
990
991 a = newdup(struct in6_addr, &ip.in6, 1);
992 if (!a)
993 return log_oom();
994
995 r = set_ensure_consume(&network->ndisc_deny_listed_prefix, &in6_addr_hash_ops, TAKE_PTR(a));
996 if (r < 0)
997 return log_oom();
998 }
999
1000 return 0;
1001 }
1002
1003 int config_parse_address_generation_type(
1004 const char *unit,
1005 const char *filename,
1006 unsigned line,
1007 const char *section,
1008 unsigned section_line,
1009 const char *lvalue,
1010 int ltype,
1011 const char *rvalue,
1012 void *data,
1013 void *userdata) {
1014
1015 _cleanup_free_ IPv6Token *token = NULL;
1016 union in_addr_union buffer;
1017 Network *network = data;
1018 const char *p;
1019 int r;
1020
1021 assert(filename);
1022 assert(lvalue);
1023 assert(rvalue);
1024 assert(data);
1025
1026 if (isempty(rvalue)) {
1027 network->ipv6_tokens = ordered_hashmap_free(network->ipv6_tokens);
1028 return 0;
1029 }
1030
1031 r = ipv6token_new(&token);
1032 if (r < 0)
1033 return log_oom();
1034
1035 if ((p = startswith(rvalue, "static:")))
1036 token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC;
1037 else if ((p = startswith(rvalue, "prefixstable:")))
1038 token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE;
1039 else {
1040 token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC;
1041 p = rvalue;
1042 }
1043
1044 r = in_addr_from_string(AF_INET6, p, &buffer);
1045 if (r < 0) {
1046 log_syntax(unit, LOG_ERR, filename, line, r,
1047 "Failed to parse IPv6 %s, ignoring: %s", lvalue, rvalue);
1048 return 0;
1049 }
1050
1051 if (in_addr_is_null(AF_INET6, &buffer)) {
1052 log_syntax(unit, LOG_ERR, filename, line, 0,
1053 "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue, rvalue);
1054 return 0;
1055 }
1056
1057 token->prefix = buffer.in6;
1058
1059 r = ordered_hashmap_ensure_allocated(&network->ipv6_tokens, &ipv6_token_hash_ops);
1060 if (r < 0)
1061 return log_oom();
1062
1063 r = ordered_hashmap_put(network->ipv6_tokens, &token->prefix, token);
1064 if (r < 0) {
1065 log_syntax(unit, LOG_ERR, filename, line, r,
1066 "Failed to store IPv6 token '%s'", rvalue);
1067 return 0;
1068 }
1069
1070 TAKE_PTR(token);
1071
1072 return 0;
1073 }
1074
1075 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
1076 "Failed to parse DHCPv6Client= setting")
1077 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
1078 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO] = "no",
1079 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
1080 [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES] = "yes",
1081 };
1082
1083 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);