]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-radv.c
Merge pull request #28764 from yuwata/core-namespace
[thirdparty/systemd.git] / src / network / networkd-radv.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2017 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <netinet/icmp6.h>
7 #include <arpa/inet.h>
8
9 #include "dns-domain.h"
10 #include "networkd-address-generation.h"
11 #include "networkd-address.h"
12 #include "networkd-dhcp-prefix-delegation.h"
13 #include "networkd-link.h"
14 #include "networkd-manager.h"
15 #include "networkd-network.h"
16 #include "networkd-queue.h"
17 #include "networkd-radv.h"
18 #include "networkd-route-util.h"
19 #include "parse-util.h"
20 #include "radv-internal.h"
21 #include "string-util.h"
22 #include "string-table.h"
23 #include "strv.h"
24
25 void network_adjust_radv(Network *network) {
26 assert(network);
27
28 /* After this function is called, network->router_prefix_delegation can be treated as a boolean. */
29
30 if (network->dhcp_pd < 0)
31 /* For backward compatibility. */
32 network->dhcp_pd = FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_DHCP6);
33
34 if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
35 if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE)
36 log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link-local addressing is disabled. "
37 "Disabling IPv6PrefixDelegation=.", network->filename);
38
39 network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
40 }
41
42 if (network->router_prefix_delegation == RADV_PREFIX_DELEGATION_NONE) {
43 network->n_router_dns = 0;
44 network->router_dns = mfree(network->router_dns);
45 network->router_search_domains = ordered_set_free(network->router_search_domains);
46 }
47
48 if (!FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_STATIC)) {
49 network->prefixes_by_section = hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
50 network->route_prefixes_by_section = hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
51 }
52 }
53
54 bool link_radv_enabled(Link *link) {
55 assert(link);
56
57 if (!link_may_have_ipv6ll(link, /* check_multicast = */ true))
58 return false;
59
60 if (link->hw_addr.length != ETH_ALEN)
61 return false;
62
63 return link->network->router_prefix_delegation;
64 }
65
66 Prefix *prefix_free(Prefix *prefix) {
67 if (!prefix)
68 return NULL;
69
70 if (prefix->network) {
71 assert(prefix->section);
72 hashmap_remove(prefix->network->prefixes_by_section, prefix->section);
73 }
74
75 config_section_free(prefix->section);
76 set_free(prefix->tokens);
77
78 return mfree(prefix);
79 }
80
81 DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix, prefix_free);
82
83 static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) {
84 _cleanup_(config_section_freep) ConfigSection *n = NULL;
85 _cleanup_(prefix_freep) Prefix *prefix = NULL;
86 int r;
87
88 assert(network);
89 assert(ret);
90 assert(filename);
91 assert(section_line > 0);
92
93 r = config_section_new(filename, section_line, &n);
94 if (r < 0)
95 return r;
96
97 prefix = hashmap_get(network->prefixes_by_section, n);
98 if (prefix) {
99 *ret = TAKE_PTR(prefix);
100 return 0;
101 }
102
103 prefix = new(Prefix, 1);
104 if (!prefix)
105 return -ENOMEM;
106
107 *prefix = (Prefix) {
108 .network = network,
109 .section = TAKE_PTR(n),
110
111 .preferred_lifetime = RADV_DEFAULT_PREFERRED_LIFETIME_USEC,
112 .valid_lifetime = RADV_DEFAULT_VALID_LIFETIME_USEC,
113 .onlink = true,
114 .address_auto_configuration = true,
115 };
116
117 r = hashmap_ensure_put(&network->prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
118 if (r < 0)
119 return r;
120
121 *ret = TAKE_PTR(prefix);
122 return 0;
123 }
124
125 RoutePrefix *route_prefix_free(RoutePrefix *prefix) {
126 if (!prefix)
127 return NULL;
128
129 if (prefix->network) {
130 assert(prefix->section);
131 hashmap_remove(prefix->network->route_prefixes_by_section, prefix->section);
132 }
133
134 config_section_free(prefix->section);
135
136 return mfree(prefix);
137 }
138
139 DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutePrefix, route_prefix_free);
140
141 static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) {
142 _cleanup_(config_section_freep) ConfigSection *n = NULL;
143 _cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
144 int r;
145
146 assert(network);
147 assert(ret);
148 assert(filename);
149 assert(section_line > 0);
150
151 r = config_section_new(filename, section_line, &n);
152 if (r < 0)
153 return r;
154
155 prefix = hashmap_get(network->route_prefixes_by_section, n);
156 if (prefix) {
157 *ret = TAKE_PTR(prefix);
158 return 0;
159 }
160
161 prefix = new(RoutePrefix, 1);
162 if (!prefix)
163 return -ENOMEM;
164
165 *prefix = (RoutePrefix) {
166 .network = network,
167 .section = TAKE_PTR(n),
168
169 .lifetime = RADV_DEFAULT_VALID_LIFETIME_USEC,
170 };
171
172 r = hashmap_ensure_put(&network->route_prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
173 if (r < 0)
174 return r;
175
176 *ret = TAKE_PTR(prefix);
177 return 0;
178 }
179
180 int link_request_radv_addresses(Link *link) {
181 Prefix *p;
182 int r;
183
184 assert(link);
185
186 if (!link_radv_enabled(link))
187 return 0;
188
189 HASHMAP_FOREACH(p, link->network->prefixes_by_section) {
190 _cleanup_set_free_ Set *addresses = NULL;
191 struct in6_addr *a;
192
193 if (!p->assign)
194 continue;
195
196 /* radv_generate_addresses() below requires the prefix length <= 64. */
197 if (p->prefixlen > 64)
198 continue;
199
200 r = radv_generate_addresses(link, p->tokens, &p->prefix, p->prefixlen, &addresses);
201 if (r < 0)
202 return r;
203
204 SET_FOREACH(a, addresses) {
205 _cleanup_(address_freep) Address *address = NULL;
206
207 r = address_new(&address);
208 if (r < 0)
209 return -ENOMEM;
210
211 address->source = NETWORK_CONFIG_SOURCE_STATIC;
212 address->family = AF_INET6;
213 address->in_addr.in6 = *a;
214 address->prefixlen = p->prefixlen;
215 address->route_metric = p->route_metric;
216
217 r = link_request_static_address(link, address);
218 if (r < 0)
219 return r;
220 }
221 }
222
223 return 0;
224 }
225
226 static uint32_t usec_to_lifetime(usec_t usec) {
227 uint64_t t;
228
229 if (usec == USEC_INFINITY)
230 return UINT32_MAX;
231
232 t = DIV_ROUND_UP(usec, USEC_PER_SEC);
233 if (t >= UINT32_MAX)
234 return UINT32_MAX;
235
236 return (uint32_t) t;
237 }
238
239 static int radv_set_prefix(Link *link, Prefix *prefix) {
240 _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
241 int r;
242
243 assert(link);
244 assert(link->radv);
245 assert(prefix);
246
247 r = sd_radv_prefix_new(&p);
248 if (r < 0)
249 return r;
250
251 r = sd_radv_prefix_set_prefix(p, &prefix->prefix, prefix->prefixlen);
252 if (r < 0)
253 return r;
254
255 r = sd_radv_prefix_set_preferred_lifetime(p, prefix->preferred_lifetime, USEC_INFINITY);
256 if (r < 0)
257 return r;
258
259 r = sd_radv_prefix_set_valid_lifetime(p, prefix->valid_lifetime, USEC_INFINITY);
260 if (r < 0)
261 return r;
262
263 r = sd_radv_prefix_set_onlink(p, prefix->onlink);
264 if (r < 0)
265 return r;
266
267 r = sd_radv_prefix_set_address_autoconfiguration(p, prefix->address_auto_configuration);
268 if (r < 0)
269 return r;
270
271 return sd_radv_add_prefix(link->radv, p);
272 }
273
274 static int radv_set_route_prefix(Link *link, RoutePrefix *prefix) {
275 _cleanup_(sd_radv_route_prefix_unrefp) sd_radv_route_prefix *p = NULL;
276 int r;
277
278 assert(link);
279 assert(link->radv);
280 assert(prefix);
281
282 r = sd_radv_route_prefix_new(&p);
283 if (r < 0)
284 return r;
285
286 r = sd_radv_route_prefix_set_prefix(p, &prefix->prefix, prefix->prefixlen);
287 if (r < 0)
288 return r;
289
290 r = sd_radv_route_prefix_set_lifetime(p, prefix->lifetime, USEC_INFINITY);
291 if (r < 0)
292 return r;
293
294 return sd_radv_add_route_prefix(link->radv, p);
295 }
296
297 static int network_get_ipv6_dns(Network *network, struct in6_addr **ret_addresses, size_t *ret_size) {
298 _cleanup_free_ struct in6_addr *addresses = NULL;
299 size_t n_addresses = 0;
300
301 assert(network);
302 assert(ret_addresses);
303 assert(ret_size);
304
305 for (size_t i = 0; i < network->n_dns; i++) {
306 union in_addr_union *addr;
307
308 if (network->dns[i]->family != AF_INET6)
309 continue;
310
311 addr = &network->dns[i]->address;
312
313 if (in_addr_is_null(AF_INET6, addr) ||
314 in_addr_is_link_local(AF_INET6, addr) ||
315 in_addr_is_localhost(AF_INET6, addr))
316 continue;
317
318 if (!GREEDY_REALLOC(addresses, n_addresses + 1))
319 return -ENOMEM;
320
321 addresses[n_addresses++] = addr->in6;
322 }
323
324 *ret_addresses = TAKE_PTR(addresses);
325 *ret_size = n_addresses;
326
327 return n_addresses;
328 }
329
330 static int radv_set_dns(Link *link, Link *uplink) {
331 _cleanup_free_ struct in6_addr *dns = NULL;
332 size_t n_dns;
333 int r;
334
335 if (!link->network->router_emit_dns)
336 return 0;
337
338 if (link->network->router_dns) {
339 struct in6_addr *p;
340
341 dns = new(struct in6_addr, link->network->n_router_dns);
342 if (!dns)
343 return -ENOMEM;
344
345 p = dns;
346 for (size_t i = 0; i < link->network->n_router_dns; i++)
347 if (in6_addr_is_null(&link->network->router_dns[i])) {
348 if (in6_addr_is_set(&link->ipv6ll_address))
349 *(p++) = link->ipv6ll_address;
350 } else
351 *(p++) = link->network->router_dns[i];
352
353 n_dns = p - dns;
354
355 goto set_dns;
356 }
357
358 r = network_get_ipv6_dns(link->network, &dns, &n_dns);
359 if (r > 0)
360 goto set_dns;
361
362 if (uplink) {
363 assert(uplink->network);
364
365 r = network_get_ipv6_dns(uplink->network, &dns, &n_dns);
366 if (r > 0)
367 goto set_dns;
368 }
369
370 return 0;
371
372 set_dns:
373 return sd_radv_set_rdnss(link->radv,
374 usec_to_lifetime(link->network->router_dns_lifetime_usec),
375 dns, n_dns);
376 }
377
378 static int radv_set_domains(Link *link, Link *uplink) {
379 _cleanup_free_ char **s = NULL; /* just free() because the strings are owned by the set */
380 OrderedSet *search_domains;
381
382 if (!link->network->router_emit_domains)
383 return 0;
384
385 search_domains = link->network->router_search_domains;
386
387 if (search_domains)
388 goto set_domains;
389
390 search_domains = link->network->search_domains;
391 if (search_domains)
392 goto set_domains;
393
394 if (uplink) {
395 assert(uplink->network);
396
397 search_domains = uplink->network->search_domains;
398 if (search_domains)
399 goto set_domains;
400 }
401
402 return 0;
403
404 set_domains:
405 s = ordered_set_get_strv(search_domains);
406 if (!s)
407 return log_oom();
408
409 return sd_radv_set_dnssl(link->radv,
410 usec_to_lifetime(link->network->router_dns_lifetime_usec),
411 s);
412
413 }
414
415 static int radv_find_uplink(Link *link, Link **ret) {
416 int r;
417
418 assert(link);
419
420 if (link->network->router_uplink_name)
421 return link_get_by_name(link->manager, link->network->router_uplink_name, ret);
422
423 if (link->network->router_uplink_index > 0)
424 return link_get_by_index(link->manager, link->network->router_uplink_index, ret);
425
426 if (link->network->router_uplink_index == UPLINK_INDEX_AUTO) {
427 if (link_dhcp_pd_is_enabled(link))
428 r = dhcp_pd_find_uplink(link, ret); /* When DHCP-PD is enabled, use its uplink. */
429 else
430 r = manager_find_uplink(link->manager, AF_INET6, link, ret);
431 if (r < 0)
432 /* It is not necessary to propagate error in automatic selection. */
433 *ret = NULL;
434 return 0;
435 }
436
437 *ret = NULL;
438 return 0;
439 }
440
441 static int radv_configure(Link *link) {
442 Link *uplink = NULL;
443 RoutePrefix *q;
444 Prefix *p;
445 int r;
446
447 assert(link);
448 assert(link->network);
449
450 if (link->radv)
451 return -EBUSY;
452
453 r = sd_radv_new(&link->radv);
454 if (r < 0)
455 return r;
456
457 r = sd_radv_attach_event(link->radv, link->manager->event, 0);
458 if (r < 0)
459 return r;
460
461 if (link->hw_addr.length == ETH_ALEN) {
462 r = sd_radv_set_mac(link->radv, &link->hw_addr.ether);
463 if (r < 0)
464 return r;
465 }
466
467 r = sd_radv_set_ifindex(link->radv, link->ifindex);
468 if (r < 0)
469 return r;
470
471 r = sd_radv_set_managed_information(link->radv, link->network->router_managed);
472 if (r < 0)
473 return r;
474
475 r = sd_radv_set_other_information(link->radv, link->network->router_other_information);
476 if (r < 0)
477 return r;
478
479 r = sd_radv_set_router_lifetime(link->radv, link->network->router_lifetime_usec);
480 if (r < 0)
481 return r;
482
483 if (link->network->router_lifetime_usec > 0) {
484 r = sd_radv_set_preference(link->radv, link->network->router_preference);
485 if (r < 0)
486 return r;
487 }
488
489 if (link->network->router_retransmit_usec > 0) {
490 r = sd_radv_set_retransmit(link->radv, DIV_ROUND_UP(link->network->router_retransmit_usec, USEC_PER_MSEC));
491 if (r < 0)
492 return r;
493 }
494
495 HASHMAP_FOREACH(p, link->network->prefixes_by_section) {
496 r = radv_set_prefix(link, p);
497 if (r < 0 && r != -EEXIST)
498 return r;
499 }
500
501 HASHMAP_FOREACH(q, link->network->route_prefixes_by_section) {
502 r = radv_set_route_prefix(link, q);
503 if (r < 0 && r != -EEXIST)
504 return r;
505 }
506
507 (void) radv_find_uplink(link, &uplink);
508
509 r = radv_set_dns(link, uplink);
510 if (r < 0)
511 return log_link_debug_errno(link, r, "Could not set RA DNS: %m");
512
513 r = radv_set_domains(link, uplink);
514 if (r < 0)
515 return log_link_debug_errno(link, r, "Could not set RA Domains: %m");
516
517 return 0;
518 }
519
520 int radv_update_mac(Link *link) {
521 bool restart;
522 int r;
523
524 assert(link);
525
526 if (!link->radv)
527 return 0;
528
529 if (link->hw_addr.length != ETH_ALEN)
530 return 0;
531
532 restart = sd_radv_is_running(link->radv);
533
534 r = sd_radv_stop(link->radv);
535 if (r < 0)
536 return r;
537
538 r = sd_radv_set_mac(link->radv, &link->hw_addr.ether);
539 if (r < 0)
540 return r;
541
542 if (restart) {
543 r = sd_radv_start(link->radv);
544 if (r < 0)
545 return r;
546 }
547
548 return 0;
549 }
550
551 static int radv_is_ready_to_configure(Link *link) {
552 bool needs_uplink = false;
553 int r;
554
555 assert(link);
556 assert(link->network);
557
558 if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false))
559 return false;
560
561 if (in6_addr_is_null(&link->ipv6ll_address))
562 return false;
563
564 if (link->hw_addr.length != ETH_ALEN || hw_addr_is_null(&link->hw_addr))
565 return false;
566
567 if (link->network->router_emit_dns && !link->network->router_dns) {
568 _cleanup_free_ struct in6_addr *dns = NULL;
569 size_t n_dns;
570
571 r = network_get_ipv6_dns(link->network, &dns, &n_dns);
572 if (r < 0)
573 return r;
574
575 needs_uplink = r == 0;
576 }
577
578 if (link->network->router_emit_domains &&
579 !link->network->router_search_domains &&
580 !link->network->search_domains)
581 needs_uplink = true;
582
583 if (needs_uplink) {
584 Link *uplink = NULL;
585
586 if (radv_find_uplink(link, &uplink) < 0)
587 return false;
588
589 if (uplink && !uplink->network)
590 return false;
591 }
592
593 return true;
594 }
595
596 static int radv_process_request(Request *req, Link *link, void *userdata) {
597 int r;
598
599 assert(link);
600
601 r = radv_is_ready_to_configure(link);
602 if (r <= 0)
603 return r;
604
605 r = radv_configure(link);
606 if (r < 0)
607 return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Advertisement engine: %m");
608
609 if (link_has_carrier(link)) {
610 r = radv_start(link);
611 if (r < 0)
612 return log_link_warning_errno(link, r, "Failed to start IPv6 Router Advertisement engine: %m");
613 }
614
615 log_link_debug(link, "IPv6 Router Advertisement engine is configured%s.",
616 link_has_carrier(link) ? " and started" : "");
617 return 1;
618 }
619
620 int link_request_radv(Link *link) {
621 int r;
622
623 assert(link);
624
625 if (!link_radv_enabled(link))
626 return 0;
627
628 if (link->radv)
629 return 0;
630
631 r = link_queue_request(link, REQUEST_TYPE_RADV, radv_process_request, NULL);
632 if (r < 0)
633 return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Advertisement engine: %m");
634
635 log_link_debug(link, "Requested configuring of the IPv6 Router Advertisement engine.");
636 return 0;
637 }
638
639 int radv_start(Link *link) {
640 int r;
641
642 assert(link);
643 assert(link->network);
644
645 if (!link->radv)
646 return 0;
647
648 if (!link_has_carrier(link))
649 return 0;
650
651 if (in6_addr_is_null(&link->ipv6ll_address))
652 return 0;
653
654 if (sd_radv_is_running(link->radv))
655 return 0;
656
657 if (link->network->dhcp_pd_announce) {
658 r = dhcp_request_prefix_delegation(link);
659 if (r < 0)
660 return log_link_debug_errno(link, r, "Failed to request DHCP delegated subnet prefix: %m");
661 }
662
663 log_link_debug(link, "Starting IPv6 Router Advertisements");
664 return sd_radv_start(link->radv);
665 }
666
667 int radv_add_prefix(
668 Link *link,
669 const struct in6_addr *prefix,
670 uint8_t prefix_len,
671 usec_t lifetime_preferred_usec,
672 usec_t lifetime_valid_usec) {
673
674 _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
675 int r;
676
677 assert(link);
678
679 if (!link->radv)
680 return 0;
681
682 r = sd_radv_prefix_new(&p);
683 if (r < 0)
684 return r;
685
686 r = sd_radv_prefix_set_prefix(p, prefix, prefix_len);
687 if (r < 0)
688 return r;
689
690 r = sd_radv_prefix_set_preferred_lifetime(p, RADV_DEFAULT_PREFERRED_LIFETIME_USEC, lifetime_preferred_usec);
691 if (r < 0)
692 return r;
693
694 r = sd_radv_prefix_set_valid_lifetime(p, RADV_DEFAULT_VALID_LIFETIME_USEC, lifetime_valid_usec);
695 if (r < 0)
696 return r;
697
698 r = sd_radv_add_prefix(link->radv, p);
699 if (r < 0 && r != -EEXIST)
700 return r;
701
702 return 0;
703 }
704
705 static int prefix_section_verify(Prefix *p) {
706 assert(p);
707
708 if (section_is_invalid(p->section))
709 return -EINVAL;
710
711 if (in6_addr_is_null(&p->prefix))
712 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
713 "%s: [IPv6Prefix] section without Prefix= field configured, "
714 "or specified prefix is the null address. "
715 "Ignoring [IPv6Prefix] section from line %u.",
716 p->section->filename, p->section->line);
717
718 if (p->prefixlen < 3 || p->prefixlen > 128)
719 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
720 "%s: Invalid prefix length %u is specified in [IPv6Prefix] section. "
721 "Valid range is 3…128. Ignoring [IPv6Prefix] section from line %u.",
722 p->section->filename, p->prefixlen, p->section->line);
723
724 if (p->prefixlen > 64) {
725 log_info("%s:%u: Unusual prefix length %u (> 64) is specified in [IPv6Prefix] section from line %s%s.",
726 p->section->filename, p->section->line,
727 p->prefixlen,
728 p->assign ? ", refusing to assign an address in " : "",
729 p->assign ? IN6_ADDR_PREFIX_TO_STRING(&p->prefix, p->prefixlen) : "");
730
731 p->assign = false;
732 }
733
734 if (p->valid_lifetime == 0)
735 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
736 "%s: The valid lifetime of prefix cannot be zero. "
737 "Ignoring [IPv6Prefix] section from line %u.",
738 p->section->filename, p->section->line);
739
740 if (p->preferred_lifetime > p->valid_lifetime)
741 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
742 "%s: The preferred lifetime %s is longer than the valid lifetime %s. "
743 "Ignoring [IPv6Prefix] section from line %u.",
744 p->section->filename,
745 FORMAT_TIMESPAN(p->preferred_lifetime, USEC_PER_SEC),
746 FORMAT_TIMESPAN(p->valid_lifetime, USEC_PER_SEC),
747 p->section->line);
748
749 return 0;
750 }
751
752 void network_drop_invalid_prefixes(Network *network) {
753 Prefix *p;
754
755 assert(network);
756
757 HASHMAP_FOREACH(p, network->prefixes_by_section)
758 if (prefix_section_verify(p) < 0)
759 prefix_free(p);
760 }
761
762 static int route_prefix_section_verify(RoutePrefix *p) {
763 if (section_is_invalid(p->section))
764 return -EINVAL;
765
766 if (p->prefixlen > 128)
767 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
768 "%s: Invalid prefix length %u is specified in [IPv6RoutePrefix] section. "
769 "Valid range is 0…128. Ignoring [IPv6RoutePrefix] section from line %u.",
770 p->section->filename, p->prefixlen, p->section->line);
771
772 if (p->lifetime == 0)
773 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
774 "%s: The lifetime of route cannot be zero. "
775 "Ignoring [IPv6RoutePrefix] section from line %u.",
776 p->section->filename, p->section->line);
777
778 return 0;
779 }
780
781 void network_drop_invalid_route_prefixes(Network *network) {
782 RoutePrefix *p;
783
784 assert(network);
785
786 HASHMAP_FOREACH(p, network->route_prefixes_by_section)
787 if (route_prefix_section_verify(p) < 0)
788 route_prefix_free(p);
789 }
790
791 int config_parse_prefix(
792 const char *unit,
793 const char *filename,
794 unsigned line,
795 const char *section,
796 unsigned section_line,
797 const char *lvalue,
798 int ltype,
799 const char *rvalue,
800 void *data,
801 void *userdata) {
802
803 _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
804 Network *network = ASSERT_PTR(userdata);
805 union in_addr_union a;
806 int r;
807
808 assert(filename);
809 assert(section);
810 assert(lvalue);
811 assert(rvalue);
812
813 r = prefix_new_static(network, filename, section_line, &p);
814 if (r < 0)
815 return log_oom();
816
817 r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &p->prefixlen);
818 if (r < 0) {
819 log_syntax(unit, LOG_WARNING, filename, line, r,
820 "Prefix is invalid, ignoring assignment: %s", rvalue);
821 return 0;
822 }
823
824 (void) in6_addr_mask(&a.in6, p->prefixlen);
825 p->prefix = a.in6;
826
827 TAKE_PTR(p);
828 return 0;
829 }
830
831 int config_parse_prefix_boolean(
832 const char *unit,
833 const char *filename,
834 unsigned line,
835 const char *section,
836 unsigned section_line,
837 const char *lvalue,
838 int ltype,
839 const char *rvalue,
840 void *data,
841 void *userdata) {
842
843 _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
844 Network *network = ASSERT_PTR(userdata);
845 int r;
846
847 assert(filename);
848 assert(section);
849 assert(lvalue);
850 assert(rvalue);
851
852 r = prefix_new_static(network, filename, section_line, &p);
853 if (r < 0)
854 return log_oom();
855
856 r = parse_boolean(rvalue);
857 if (r < 0) {
858 log_syntax(unit, LOG_WARNING, filename, line, r,
859 "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
860 return 0;
861 }
862
863 if (streq(lvalue, "OnLink"))
864 p->onlink = r;
865 else if (streq(lvalue, "AddressAutoconfiguration"))
866 p->address_auto_configuration = r;
867 else if (streq(lvalue, "Assign"))
868 p->assign = r;
869 else
870 assert_not_reached();
871
872 TAKE_PTR(p);
873 return 0;
874 }
875
876 int config_parse_prefix_lifetime(
877 const char *unit,
878 const char *filename,
879 unsigned line,
880 const char *section,
881 unsigned section_line,
882 const char *lvalue,
883 int ltype,
884 const char *rvalue,
885 void *data,
886 void *userdata) {
887
888 _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
889 Network *network = ASSERT_PTR(userdata);
890 usec_t usec;
891 int r;
892
893 assert(filename);
894 assert(section);
895 assert(lvalue);
896 assert(rvalue);
897
898 r = prefix_new_static(network, filename, section_line, &p);
899 if (r < 0)
900 return log_oom();
901
902 r = parse_sec(rvalue, &usec);
903 if (r < 0) {
904 log_syntax(unit, LOG_WARNING, filename, line, r,
905 "Lifetime is invalid, ignoring assignment: %s", rvalue);
906 return 0;
907 }
908
909 if (usec != USEC_INFINITY && DIV_ROUND_UP(usec, USEC_PER_SEC) >= UINT32_MAX) {
910 log_syntax(unit, LOG_WARNING, filename, line, 0,
911 "Lifetime is too long, ignoring assignment: %s", rvalue);
912 return 0;
913 }
914
915 if (streq(lvalue, "PreferredLifetimeSec"))
916 p->preferred_lifetime = usec;
917 else if (streq(lvalue, "ValidLifetimeSec"))
918 p->valid_lifetime = usec;
919 else
920 assert_not_reached();
921
922 TAKE_PTR(p);
923 return 0;
924 }
925
926 int config_parse_prefix_metric(
927 const char *unit,
928 const char *filename,
929 unsigned line,
930 const char *section,
931 unsigned section_line,
932 const char *lvalue,
933 int ltype,
934 const char *rvalue,
935 void *data,
936 void *userdata) {
937
938 _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
939 Network *network = ASSERT_PTR(userdata);
940 int r;
941
942 assert(filename);
943 assert(section);
944 assert(lvalue);
945 assert(rvalue);
946
947 r = prefix_new_static(network, filename, section_line, &p);
948 if (r < 0)
949 return log_oom();
950
951 r = safe_atou32(rvalue, &p->route_metric);
952 if (r < 0) {
953 log_syntax(unit, LOG_WARNING, filename, line, r,
954 "Failed to parse %s=, ignoring assignment: %s",
955 lvalue, rvalue);
956 return 0;
957 }
958
959 TAKE_PTR(p);
960 return 0;
961 }
962
963 int config_parse_prefix_token(
964 const char *unit,
965 const char *filename,
966 unsigned line,
967 const char *section,
968 unsigned section_line,
969 const char *lvalue,
970 int ltype,
971 const char *rvalue,
972 void *data,
973 void *userdata) {
974
975 _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
976 Network *network = ASSERT_PTR(userdata);
977 int r;
978
979 assert(filename);
980 assert(section);
981 assert(lvalue);
982 assert(rvalue);
983
984 r = prefix_new_static(network, filename, section_line, &p);
985 if (r < 0)
986 return log_oom();
987
988 r = config_parse_address_generation_type(unit, filename, line, section, section_line,
989 lvalue, ltype, rvalue, &p->tokens, userdata);
990 if (r < 0)
991 return r;
992
993 TAKE_PTR(p);
994 return 0;
995 }
996
997 int config_parse_route_prefix(
998 const char *unit,
999 const char *filename,
1000 unsigned line,
1001 const char *section,
1002 unsigned section_line,
1003 const char *lvalue,
1004 int ltype,
1005 const char *rvalue,
1006 void *data,
1007 void *userdata) {
1008
1009 _cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL;
1010 Network *network = ASSERT_PTR(userdata);
1011 union in_addr_union a;
1012 int r;
1013
1014 assert(filename);
1015 assert(section);
1016 assert(lvalue);
1017 assert(rvalue);
1018
1019 r = route_prefix_new_static(network, filename, section_line, &p);
1020 if (r < 0)
1021 return log_oom();
1022
1023 r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &p->prefixlen);
1024 if (r < 0) {
1025 log_syntax(unit, LOG_WARNING, filename, line, r,
1026 "Route prefix is invalid, ignoring assignment: %s", rvalue);
1027 return 0;
1028 }
1029
1030 (void) in6_addr_mask(&a.in6, p->prefixlen);
1031 p->prefix = a.in6;
1032
1033 TAKE_PTR(p);
1034 return 0;
1035 }
1036
1037 int config_parse_route_prefix_lifetime(
1038 const char *unit,
1039 const char *filename,
1040 unsigned line,
1041 const char *section,
1042 unsigned section_line,
1043 const char *lvalue,
1044 int ltype,
1045 const char *rvalue,
1046 void *data,
1047 void *userdata) {
1048
1049 _cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL;
1050 Network *network = ASSERT_PTR(userdata);
1051 usec_t usec;
1052 int r;
1053
1054 assert(filename);
1055 assert(section);
1056 assert(lvalue);
1057 assert(rvalue);
1058
1059 r = route_prefix_new_static(network, filename, section_line, &p);
1060 if (r < 0)
1061 return log_oom();
1062
1063 r = parse_sec(rvalue, &usec);
1064 if (r < 0) {
1065 log_syntax(unit, LOG_WARNING, filename, line, r,
1066 "Route lifetime is invalid, ignoring assignment: %s", rvalue);
1067 return 0;
1068 }
1069
1070 if (usec != USEC_INFINITY && DIV_ROUND_UP(usec, USEC_PER_SEC) >= UINT32_MAX) {
1071 log_syntax(unit, LOG_WARNING, filename, line, 0,
1072 "Lifetime is too long, ignoring assignment: %s", rvalue);
1073 return 0;
1074 }
1075
1076 p->lifetime = usec;
1077
1078 TAKE_PTR(p);
1079 return 0;
1080 }
1081
1082 int config_parse_radv_dns(
1083 const char *unit,
1084 const char *filename,
1085 unsigned line,
1086 const char *section,
1087 unsigned section_line,
1088 const char *lvalue,
1089 int ltype,
1090 const char *rvalue,
1091 void *data,
1092 void *userdata) {
1093
1094 Network *n = data;
1095 int r;
1096
1097 assert(filename);
1098 assert(lvalue);
1099 assert(rvalue);
1100
1101 if (isempty(rvalue)) {
1102 n->n_router_dns = 0;
1103 n->router_dns = mfree(n->router_dns);
1104 return 0;
1105 }
1106
1107 for (const char *p = rvalue;;) {
1108 _cleanup_free_ char *w = NULL;
1109 union in_addr_union a;
1110
1111 r = extract_first_word(&p, &w, NULL, 0);
1112 if (r == -ENOMEM)
1113 return log_oom();
1114 if (r < 0) {
1115 log_syntax(unit, LOG_WARNING, filename, line, r,
1116 "Failed to extract word, ignoring: %s", rvalue);
1117 return 0;
1118 }
1119 if (r == 0)
1120 return 0;
1121
1122 if (streq(w, "_link_local"))
1123 a = IN_ADDR_NULL;
1124 else {
1125 r = in_addr_from_string(AF_INET6, w, &a);
1126 if (r < 0) {
1127 log_syntax(unit, LOG_WARNING, filename, line, r,
1128 "Failed to parse DNS server address, ignoring: %s", w);
1129 continue;
1130 }
1131
1132 if (in_addr_is_null(AF_INET6, &a)) {
1133 log_syntax(unit, LOG_WARNING, filename, line, 0,
1134 "DNS server address is null, ignoring: %s", w);
1135 continue;
1136 }
1137 }
1138
1139 struct in6_addr *m;
1140 m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
1141 if (!m)
1142 return log_oom();
1143
1144 m[n->n_router_dns++] = a.in6;
1145 n->router_dns = m;
1146 }
1147 }
1148
1149 int config_parse_radv_search_domains(
1150 const char *unit,
1151 const char *filename,
1152 unsigned line,
1153 const char *section,
1154 unsigned section_line,
1155 const char *lvalue,
1156 int ltype,
1157 const char *rvalue,
1158 void *data,
1159 void *userdata) {
1160
1161 Network *n = data;
1162 int r;
1163
1164 assert(filename);
1165 assert(lvalue);
1166 assert(rvalue);
1167
1168 if (isempty(rvalue)) {
1169 n->router_search_domains = ordered_set_free(n->router_search_domains);
1170 return 0;
1171 }
1172
1173 for (const char *p = rvalue;;) {
1174 _cleanup_free_ char *w = NULL, *idna = NULL;
1175
1176 r = extract_first_word(&p, &w, NULL, 0);
1177 if (r == -ENOMEM)
1178 return log_oom();
1179 if (r < 0) {
1180 log_syntax(unit, LOG_WARNING, filename, line, r,
1181 "Failed to extract word, ignoring: %s", rvalue);
1182 return 0;
1183 }
1184 if (r == 0)
1185 return 0;
1186
1187 r = dns_name_apply_idna(w, &idna);
1188 if (r < 0) {
1189 log_syntax(unit, LOG_WARNING, filename, line, r,
1190 "Failed to apply IDNA to domain name '%s', ignoring: %m", w);
1191 continue;
1192 } else if (r == 0)
1193 /* transfer ownership to simplify subsequent operations */
1194 idna = TAKE_PTR(w);
1195
1196 r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops_free);
1197 if (r < 0)
1198 return log_oom();
1199
1200 r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna));
1201 if (r < 0)
1202 return log_oom();
1203 }
1204 }
1205
1206 static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = {
1207 [RADV_PREFIX_DELEGATION_NONE] = "no",
1208 [RADV_PREFIX_DELEGATION_STATIC] = "static",
1209 [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6",
1210 [RADV_PREFIX_DELEGATION_BOTH] = "yes",
1211 };
1212
1213 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
1214 radv_prefix_delegation,
1215 RADVPrefixDelegation,
1216 RADV_PREFIX_DELEGATION_BOTH);
1217
1218 int config_parse_router_prefix_delegation(
1219 const char *unit,
1220 const char *filename,
1221 unsigned line,
1222 const char *section,
1223 unsigned section_line,
1224 const char *lvalue,
1225 int ltype,
1226 const char *rvalue,
1227 void *data,
1228 void *userdata) {
1229
1230 RADVPrefixDelegation val, *ra = ASSERT_PTR(data);
1231 int r;
1232
1233 assert(filename);
1234 assert(lvalue);
1235 assert(rvalue);
1236
1237 if (streq(lvalue, "IPv6SendRA")) {
1238 r = parse_boolean(rvalue);
1239 if (r < 0) {
1240 log_syntax(unit, LOG_WARNING, filename, line, r,
1241 "Invalid %s= setting, ignoring assignment: %s", lvalue, rvalue);
1242 return 0;
1243 }
1244
1245 /* When IPv6SendRA= is enabled, only static prefixes are sent by default, and users
1246 * need to explicitly enable DHCPv6PrefixDelegation=. */
1247 *ra = r ? RADV_PREFIX_DELEGATION_STATIC : RADV_PREFIX_DELEGATION_NONE;
1248 return 0;
1249 }
1250
1251 /* For backward compatibility */
1252 val = radv_prefix_delegation_from_string(rvalue);
1253 if (val < 0) {
1254 log_syntax(unit, LOG_WARNING, filename, line, val,
1255 "Invalid %s= setting, ignoring assignment: %s", lvalue, rvalue);
1256 return 0;
1257 }
1258
1259 *ra = val;
1260 return 0;
1261 }
1262
1263 int config_parse_router_lifetime(
1264 const char *unit,
1265 const char *filename,
1266 unsigned line,
1267 const char *section,
1268 unsigned section_line,
1269 const char *lvalue,
1270 int ltype,
1271 const char *rvalue,
1272 void *data,
1273 void *userdata) {
1274
1275 usec_t usec, *lifetime = ASSERT_PTR(data);
1276 int r;
1277
1278 assert(filename);
1279 assert(section);
1280 assert(lvalue);
1281 assert(rvalue);
1282
1283 if (isempty(rvalue)) {
1284 *lifetime = RADV_DEFAULT_ROUTER_LIFETIME_USEC;
1285 return 0;
1286 }
1287
1288 r = parse_sec(rvalue, &usec);
1289 if (r < 0) {
1290 log_syntax(unit, LOG_WARNING, filename, line, r,
1291 "Failed to parse router lifetime, ignoring assignment: %s", rvalue);
1292 return 0;
1293 }
1294 if (usec > 0) {
1295 if (usec < RADV_MIN_ROUTER_LIFETIME_USEC) {
1296 log_syntax(unit, LOG_WARNING, filename, line, 0,
1297 "Router lifetime %s is too short, using %s.",
1298 FORMAT_TIMESPAN(usec, USEC_PER_SEC),
1299 FORMAT_TIMESPAN(RADV_MIN_ROUTER_LIFETIME_USEC, USEC_PER_SEC));
1300 usec = RADV_MIN_ROUTER_LIFETIME_USEC;
1301 } else if (usec > RADV_MAX_ROUTER_LIFETIME_USEC) {
1302 log_syntax(unit, LOG_WARNING, filename, line, 0,
1303 "Router lifetime %s is too large, using %s.",
1304 FORMAT_TIMESPAN(usec, USEC_PER_SEC),
1305 FORMAT_TIMESPAN(RADV_MAX_ROUTER_LIFETIME_USEC, USEC_PER_SEC));
1306 usec = RADV_MAX_ROUTER_LIFETIME_USEC;
1307 }
1308 }
1309
1310 *lifetime = usec;
1311 return 0;
1312 }
1313
1314 int config_parse_router_retransmit(
1315 const char *unit,
1316 const char *filename,
1317 unsigned line,
1318 const char *section,
1319 unsigned section_line,
1320 const char *lvalue,
1321 int ltype,
1322 const char *rvalue,
1323 void *data,
1324 void *userdata) {
1325
1326 usec_t usec, *router_retransmit_usec = ASSERT_PTR(data);
1327 int r;
1328
1329 assert(filename);
1330 assert(section);
1331 assert(lvalue);
1332 assert(rvalue);
1333
1334 if (isempty(rvalue)) {
1335 *router_retransmit_usec = 0;
1336 return 0;
1337 }
1338
1339 r = parse_sec(rvalue, &usec);
1340 if (r < 0) {
1341 log_syntax(unit, LOG_WARNING, filename, line, r,
1342 "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
1343 return 0;
1344 }
1345
1346 if (usec != USEC_INFINITY &&
1347 DIV_ROUND_UP(usec, USEC_PER_MSEC) > UINT32_MAX) {
1348 log_syntax(unit, LOG_WARNING, filename, line, 0,
1349 "Invalid %s= must be in the range 0...%"PRIu32"Sec, ignoring: %s", lvalue, UINT32_MAX, rvalue);
1350 return 0;
1351 }
1352
1353 *router_retransmit_usec = usec;
1354 return 0;
1355 }
1356
1357 int config_parse_router_preference(
1358 const char *unit,
1359 const char *filename,
1360 unsigned line,
1361 const char *section,
1362 unsigned section_line,
1363 const char *lvalue,
1364 int ltype,
1365 const char *rvalue,
1366 void *data,
1367 void *userdata) {
1368
1369 Network *network = userdata;
1370
1371 assert(filename);
1372 assert(section);
1373 assert(lvalue);
1374 assert(rvalue);
1375 assert(data);
1376
1377 if (streq(rvalue, "high"))
1378 network->router_preference = SD_NDISC_PREFERENCE_HIGH;
1379 else if (STR_IN_SET(rvalue, "medium", "normal", "default"))
1380 network->router_preference = SD_NDISC_PREFERENCE_MEDIUM;
1381 else if (streq(rvalue, "low"))
1382 network->router_preference = SD_NDISC_PREFERENCE_LOW;
1383 else
1384 log_syntax(unit, LOG_WARNING, filename, line, 0,
1385 "Invalid router preference, ignoring assignment: %s", rvalue);
1386
1387 return 0;
1388 }