1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2017 Intel Corporation. All rights reserved.
6 #include <netinet/icmp6.h>
7 #include <netinet/in.h>
12 #include "alloc-util.h"
13 #include "dns-domain.h"
14 #include "ether-addr-util.h"
15 #include "event-util.h"
17 #include "icmp6-util.h"
18 #include "in-addr-util.h"
21 #include "memory-util.h"
22 #include "network-common.h"
23 #include "radv-internal.h"
24 #include "random-util.h"
25 #include "socket-util.h"
26 #include "string-util.h"
29 int sd_radv_new(sd_radv
**ret
) {
30 _cleanup_(sd_radv_unrefp
) sd_radv
*ra
= NULL
;
32 assert_return(ret
, -EINVAL
);
41 .lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
49 int sd_radv_attach_event(sd_radv
*ra
, sd_event
*event
, int64_t priority
) {
52 assert_return(ra
, -EINVAL
);
53 assert_return(!ra
->event
, -EBUSY
);
56 ra
->event
= sd_event_ref(event
);
58 r
= sd_event_default(&ra
->event
);
63 ra
->event_priority
= priority
;
68 int sd_radv_detach_event(sd_radv
*ra
) {
70 assert_return(ra
, -EINVAL
);
72 ra
->event
= sd_event_unref(ra
->event
);
76 sd_event
*sd_radv_get_event(sd_radv
*ra
) {
77 assert_return(ra
, NULL
);
82 int sd_radv_is_running(sd_radv
*ra
) {
83 assert_return(ra
, false);
85 return ra
->state
!= RADV_STATE_IDLE
;
88 static void radv_reset(sd_radv
*ra
) {
91 (void) event_source_disable(ra
->timeout_event_source
);
93 ra
->recv_event_source
= sd_event_source_disable_unref(ra
->recv_event_source
);
98 static sd_radv
*radv_free(sd_radv
*ra
) {
102 while (ra
->prefixes
) {
103 sd_radv_prefix
*p
= ra
->prefixes
;
105 LIST_REMOVE(prefix
, ra
->prefixes
, p
);
106 sd_radv_prefix_unref(p
);
109 while (ra
->route_prefixes
) {
110 sd_radv_route_prefix
*p
= ra
->route_prefixes
;
112 LIST_REMOVE(prefix
, ra
->route_prefixes
, p
);
113 sd_radv_route_prefix_unref(p
);
121 sd_event_source_unref(ra
->timeout_event_source
);
122 sd_radv_detach_event(ra
);
124 ra
->fd
= safe_close(ra
->fd
);
130 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv
, sd_radv
, radv_free
);
132 static bool router_lifetime_is_valid(usec_t lifetime_usec
) {
133 return lifetime_usec
== 0 ||
134 (lifetime_usec
>= RADV_MIN_ROUTER_LIFETIME_USEC
&&
135 lifetime_usec
<= RADV_MAX_ROUTER_LIFETIME_USEC
);
138 static be32_t
usec_to_be32_sec(usec_t usec
) {
139 if (usec
== USEC_INFINITY
)
140 /* UINT32_MAX is handled as infinity. */
141 return htobe32(UINT32_MAX
);
143 if (usec
>= UINT32_MAX
* USEC_PER_SEC
)
144 /* Finite but too large. Let's use the largest finite value. */
145 return htobe32(UINT32_MAX
- 1);
147 return htobe32(usec
/ USEC_PER_SEC
);
150 static int radv_send(sd_radv
*ra
, const struct in6_addr
*dst
, usec_t lifetime_usec
) {
151 sd_radv_route_prefix
*rt
;
153 struct sockaddr_in6 dst_addr
= {
154 .sin6_family
= AF_INET6
,
155 .sin6_addr
= IN6ADDR_ALL_NODES_MULTICAST_INIT
,
157 struct nd_router_advert adv
= {};
159 struct nd_opt_hdr opthdr
;
160 struct ether_addr slladdr
;
161 } _packed_ opt_mac
= {
163 .nd_opt_type
= ND_OPT_SOURCE_LINKADDR
,
164 .nd_opt_len
= (sizeof(struct nd_opt_hdr
) +
165 sizeof(struct ether_addr
) - 1) /8 + 1,
168 struct nd_opt_mtu opt_mtu
= {
169 .nd_opt_mtu_type
= ND_OPT_MTU
,
172 /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, N routes, RDNSS
174 struct iovec iov
[5 + ra
->n_prefixes
+ ra
->n_route_prefixes
];
175 struct msghdr msg
= {
176 .msg_name
= &dst_addr
,
177 .msg_namelen
= sizeof(dst_addr
),
184 assert(router_lifetime_is_valid(lifetime_usec
));
186 r
= sd_event_now(ra
->event
, clock_boottime_or_monotonic(), &time_now
);
190 if (dst
&& in6_addr_is_set(dst
))
191 dst_addr
.sin6_addr
= *dst
;
193 adv
.nd_ra_type
= ND_ROUTER_ADVERT
;
194 adv
.nd_ra_curhoplimit
= ra
->hop_limit
;
195 adv
.nd_ra_flags_reserved
= ra
->flags
;
196 assert_cc(RADV_MAX_ROUTER_LIFETIME_USEC
<= UINT16_MAX
* USEC_PER_SEC
);
197 adv
.nd_ra_router_lifetime
= htobe16(DIV_ROUND_UP(lifetime_usec
, USEC_PER_SEC
));
198 iov
[msg
.msg_iovlen
++] = IOVEC_MAKE(&adv
, sizeof(adv
));
200 /* MAC address is optional, either because the link does not use L2
201 addresses or load sharing is desired. See RFC 4861, Section 4.2 */
202 if (!ether_addr_is_null(&ra
->mac_addr
)) {
203 opt_mac
.slladdr
= ra
->mac_addr
;
204 iov
[msg
.msg_iovlen
++] = IOVEC_MAKE(&opt_mac
, sizeof(opt_mac
));
208 opt_mtu
.nd_opt_mtu_mtu
= htobe32(ra
->mtu
);
209 iov
[msg
.msg_iovlen
++] = IOVEC_MAKE(&opt_mtu
, sizeof(opt_mtu
));
212 LIST_FOREACH(prefix
, p
, ra
->prefixes
) {
213 usec_t lifetime_valid_usec
, lifetime_preferred_usec
;
215 lifetime_valid_usec
= MIN(usec_sub_unsigned(p
->valid_until
, time_now
),
216 p
->lifetime_valid_usec
);
218 lifetime_preferred_usec
= MIN3(usec_sub_unsigned(p
->preferred_until
, time_now
),
219 p
->lifetime_preferred_usec
,
220 lifetime_valid_usec
);
222 p
->opt
.lifetime_valid
= usec_to_be32_sec(lifetime_valid_usec
);
223 p
->opt
.lifetime_preferred
= usec_to_be32_sec(lifetime_preferred_usec
);
225 iov
[msg
.msg_iovlen
++] = IOVEC_MAKE(&p
->opt
, sizeof(p
->opt
));
228 LIST_FOREACH(prefix
, rt
, ra
->route_prefixes
) {
229 rt
->opt
.lifetime
= usec_to_be32_sec(MIN(usec_sub_unsigned(rt
->valid_until
, time_now
),
232 iov
[msg
.msg_iovlen
++] = IOVEC_MAKE(&rt
->opt
, sizeof(rt
->opt
));
236 iov
[msg
.msg_iovlen
++] = IOVEC_MAKE(ra
->rdnss
, ra
->rdnss
->length
* 8);
239 iov
[msg
.msg_iovlen
++] = IOVEC_MAKE(ra
->dnssl
, ra
->dnssl
->length
* 8);
241 if (sendmsg(ra
->fd
, &msg
, 0) < 0)
247 static int radv_recv(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
248 sd_radv
*ra
= userdata
;
249 _cleanup_free_
char *addr
= NULL
;
251 triple_timestamp timestamp
;
254 _cleanup_free_
char *buf
= NULL
;
260 buflen
= next_datagram_size_fd(fd
);
262 if (ERRNO_IS_TRANSIENT(buflen
) || ERRNO_IS_DISCONNECT(buflen
))
265 log_radv_errno(ra
, buflen
, "Failed to determine datagram size to read, ignoring: %m");
269 buf
= new0(char, buflen
);
273 r
= icmp6_receive(fd
, buf
, buflen
, &src
, ×tamp
);
275 if (ERRNO_IS_TRANSIENT(r
) || ERRNO_IS_DISCONNECT(r
))
280 (void) in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &src
, &addr
);
281 log_radv(ra
, "Received RS from non-link-local address %s. Ignoring", addr
);
285 log_radv(ra
, "Received RS with invalid hop limit. Ignoring.");
289 log_radv(ra
, "Received invalid source address from ICMPv6 socket. Ignoring.");
293 log_radv_errno(ra
, r
, "Unexpected error receiving from ICMPv6 socket, ignoring: %m");
300 if ((size_t) buflen
< sizeof(struct nd_router_solicit
)) {
301 log_radv(ra
, "Too short packet received, ignoring");
305 (void) in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &src
, &addr
);
307 r
= radv_send(ra
, &src
, ra
->lifetime_usec
);
309 log_radv_errno(ra
, r
, "Unable to send solicited Router Advertisement to %s, ignoring: %m", strnull(addr
));
311 log_radv(ra
, "Sent solicited Router Advertisement to %s", strnull(addr
));
316 static int radv_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
317 usec_t min_timeout
, max_timeout
, time_now
, timeout
;
318 sd_radv
*ra
= userdata
;
324 assert(router_lifetime_is_valid(ra
->lifetime_usec
));
326 r
= sd_event_now(ra
->event
, clock_boottime_or_monotonic(), &time_now
);
330 r
= radv_send(ra
, NULL
, ra
->lifetime_usec
);
332 log_radv_errno(ra
, r
, "Unable to send Router Advertisement: %m");
334 /* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
335 if (ra
->ra_sent
< RADV_MAX_INITIAL_RTR_ADVERTISEMENTS
)
336 max_timeout
= RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC
;
338 max_timeout
= RADV_DEFAULT_MAX_TIMEOUT_USEC
;
340 /* RFC 4861, Section 6.2.1, lifetime must be at least MaxRtrAdvInterval,
341 * so lower the interval here */
342 if (ra
->lifetime_usec
> 0)
343 max_timeout
= MIN(max_timeout
, ra
->lifetime_usec
);
345 if (max_timeout
>= 9 * USEC_PER_SEC
)
346 min_timeout
= max_timeout
/ 3;
348 min_timeout
= max_timeout
* 3 / 4;
350 /* RFC 4861, Section 6.2.1.
351 * MaxRtrAdvInterval MUST be no less than 4 seconds and no greater than 1800 seconds.
352 * MinRtrAdvInterval MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval. */
353 assert(max_timeout
>= RADV_MIN_MAX_TIMEOUT_USEC
);
354 assert(max_timeout
<= RADV_MAX_MAX_TIMEOUT_USEC
);
355 assert(min_timeout
>= RADV_MIN_MIN_TIMEOUT_USEC
);
356 assert(min_timeout
<= max_timeout
* 3 / 4);
358 timeout
= min_timeout
+ random_u64_range(max_timeout
- min_timeout
);
359 log_radv(ra
, "Next Router Advertisement in %s", FORMAT_TIMESPAN(timeout
, USEC_PER_SEC
));
361 r
= event_reset_time(ra
->event
, &ra
->timeout_event_source
,
362 clock_boottime_or_monotonic(),
363 usec_add(time_now
, timeout
), MSEC_PER_SEC
,
365 ra
->event_priority
, "radv-timeout", true);
379 int sd_radv_stop(sd_radv
*ra
) {
385 if (ra
->state
== RADV_STATE_IDLE
)
388 log_radv(ra
, "Stopping IPv6 Router Advertisement daemon");
390 /* RFC 4861, Section 6.2.5, send at least one Router Advertisement
391 with zero lifetime */
392 r
= radv_send(ra
, NULL
, 0);
394 log_radv_errno(ra
, r
, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
397 ra
->fd
= safe_close(ra
->fd
);
398 ra
->state
= RADV_STATE_IDLE
;
403 int sd_radv_start(sd_radv
*ra
) {
406 assert_return(ra
, -EINVAL
);
407 assert_return(ra
->event
, -EINVAL
);
408 assert_return(ra
->ifindex
> 0, -EINVAL
);
410 if (ra
->state
!= RADV_STATE_IDLE
)
413 r
= event_reset_time(ra
->event
, &ra
->timeout_event_source
,
414 clock_boottime_or_monotonic(),
417 ra
->event_priority
, "radv-timeout", true);
421 r
= icmp6_bind_router_advertisement(ra
->ifindex
);
427 r
= sd_event_add_io(ra
->event
, &ra
->recv_event_source
, ra
->fd
, EPOLLIN
, radv_recv
, ra
);
431 r
= sd_event_source_set_priority(ra
->recv_event_source
, ra
->event_priority
);
435 (void) sd_event_source_set_description(ra
->recv_event_source
, "radv-receive-message");
437 ra
->state
= RADV_STATE_ADVERTISING
;
439 log_radv(ra
, "Started IPv6 Router Advertisement daemon");
449 int sd_radv_set_ifindex(sd_radv
*ra
, int ifindex
) {
450 assert_return(ra
, -EINVAL
);
451 assert_return(ifindex
> 0, -EINVAL
);
453 if (ra
->state
!= RADV_STATE_IDLE
)
456 ra
->ifindex
= ifindex
;
461 int sd_radv_set_ifname(sd_radv
*ra
, const char *ifname
) {
462 assert_return(ra
, -EINVAL
);
463 assert_return(ifname
, -EINVAL
);
465 if (!ifname_valid_full(ifname
, IFNAME_VALID_ALTERNATIVE
))
468 return free_and_strdup(&ra
->ifname
, ifname
);
471 int sd_radv_get_ifname(sd_radv
*ra
, const char **ret
) {
474 assert_return(ra
, -EINVAL
);
476 r
= get_ifname(ra
->ifindex
, &ra
->ifname
);
486 int sd_radv_set_mac(sd_radv
*ra
, const struct ether_addr
*mac_addr
) {
487 assert_return(ra
, -EINVAL
);
489 if (ra
->state
!= RADV_STATE_IDLE
)
493 ra
->mac_addr
= *mac_addr
;
500 int sd_radv_set_mtu(sd_radv
*ra
, uint32_t mtu
) {
501 assert_return(ra
, -EINVAL
);
502 assert_return(mtu
>= 1280, -EINVAL
);
509 int sd_radv_set_hop_limit(sd_radv
*ra
, uint8_t hop_limit
) {
510 assert_return(ra
, -EINVAL
);
512 if (ra
->state
!= RADV_STATE_IDLE
)
515 ra
->hop_limit
= hop_limit
;
520 int sd_radv_set_router_lifetime(sd_radv
*ra
, uint64_t lifetime_usec
) {
521 assert_return(ra
, -EINVAL
);
523 if (ra
->state
!= RADV_STATE_IDLE
)
526 if (!router_lifetime_is_valid(lifetime_usec
))
529 /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the preference value MUST be set
530 * to (00) by the sender..." */
531 if (lifetime_usec
== 0 &&
532 (ra
->flags
& (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM
<< 3))
535 ra
->lifetime_usec
= lifetime_usec
;
540 int sd_radv_set_managed_information(sd_radv
*ra
, int managed
) {
541 assert_return(ra
, -EINVAL
);
543 if (ra
->state
!= RADV_STATE_IDLE
)
546 SET_FLAG(ra
->flags
, ND_RA_FLAG_MANAGED
, managed
);
551 int sd_radv_set_other_information(sd_radv
*ra
, int other
) {
552 assert_return(ra
, -EINVAL
);
554 if (ra
->state
!= RADV_STATE_IDLE
)
557 SET_FLAG(ra
->flags
, ND_RA_FLAG_OTHER
, other
);
562 int sd_radv_set_preference(sd_radv
*ra
, unsigned preference
) {
563 assert_return(ra
, -EINVAL
);
564 assert_return(IN_SET(preference
,
565 SD_NDISC_PREFERENCE_LOW
,
566 SD_NDISC_PREFERENCE_MEDIUM
,
567 SD_NDISC_PREFERENCE_HIGH
), -EINVAL
);
569 /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the preference value MUST be set
570 * to (00) by the sender..." */
571 if (ra
->lifetime_usec
== 0 && preference
!= SD_NDISC_PREFERENCE_MEDIUM
)
574 ra
->flags
= (ra
->flags
& ~(0x3 << 3)) | (preference
<< 3);
579 int sd_radv_add_prefix(sd_radv
*ra
, sd_radv_prefix
*p
) {
580 _cleanup_free_
char *addr_p
= NULL
;
581 sd_radv_prefix
*cur
, *found
= NULL
;
584 assert_return(ra
, -EINVAL
);
585 assert_return(p
, -EINVAL
);
587 /* Refuse prefixes that don't have a prefix set */
588 if (in6_addr_is_null(&p
->opt
.in6_addr
))
591 (void) in6_addr_prefix_to_string(&p
->opt
.in6_addr
, p
->opt
.prefixlen
, &addr_p
);
593 LIST_FOREACH(prefix
, cur
, ra
->prefixes
) {
595 r
= in_addr_prefix_intersect(AF_INET6
,
596 (const union in_addr_union
*) &cur
->opt
.in6_addr
,
598 (const union in_addr_union
*) &p
->opt
.in6_addr
,
605 if (cur
->opt
.prefixlen
== p
->opt
.prefixlen
) {
610 _cleanup_free_
char *addr_cur
= NULL
;
611 (void) in6_addr_prefix_to_string(&cur
->opt
.in6_addr
, cur
->opt
.prefixlen
, &addr_cur
);
612 return log_radv_errno(ra
, SYNTHETIC_ERRNO(EEXIST
),
613 "IPv6 prefix %s conflicts with %s, ignoring.",
614 strna(addr_p
), strna(addr_cur
));
618 /* p and cur may be equivalent. First increment the reference counter. */
619 sd_radv_prefix_ref(p
);
621 /* Then, remove the old entry. */
622 LIST_REMOVE(prefix
, ra
->prefixes
, found
);
623 sd_radv_prefix_unref(found
);
625 /* Finally, add the new entry. */
626 LIST_APPEND(prefix
, ra
->prefixes
, p
);
628 log_radv(ra
, "Updated/replaced IPv6 prefix %s (preferred: %s, valid: %s)",
630 FORMAT_TIMESPAN(p
->lifetime_preferred_usec
, USEC_PER_SEC
),
631 FORMAT_TIMESPAN(p
->lifetime_valid_usec
, USEC_PER_SEC
));
633 /* The prefix is new. Let's simply add it. */
635 sd_radv_prefix_ref(p
);
636 LIST_APPEND(prefix
, ra
->prefixes
, p
);
639 log_radv(ra
, "Added prefix %s", strna(addr_p
));
642 if (ra
->state
== RADV_STATE_IDLE
)
645 if (ra
->ra_sent
== 0)
648 /* If RAs have already been sent, send an RA immediately to announce the newly-added prefix */
649 r
= radv_send(ra
, NULL
, ra
->lifetime_usec
);
651 log_radv_errno(ra
, r
, "Unable to send Router Advertisement for added prefix %s: %m",
654 log_radv(ra
, "Sent Router Advertisement for added/updated prefix %s.", strna(addr_p
));
659 void sd_radv_remove_prefix(
661 const struct in6_addr
*prefix
,
662 unsigned char prefixlen
) {
672 LIST_FOREACH(prefix
, cur
, ra
->prefixes
) {
673 if (prefixlen
!= cur
->opt
.prefixlen
)
676 if (!in6_addr_equal(prefix
, &cur
->opt
.in6_addr
))
679 LIST_REMOVE(prefix
, ra
->prefixes
, cur
);
681 sd_radv_prefix_unref(cur
);
686 int sd_radv_add_route_prefix(sd_radv
*ra
, sd_radv_route_prefix
*p
) {
687 _cleanup_free_
char *addr_p
= NULL
;
688 sd_radv_route_prefix
*cur
, *found
= NULL
;
691 assert_return(ra
, -EINVAL
);
692 assert_return(p
, -EINVAL
);
694 (void) in6_addr_prefix_to_string(&p
->opt
.in6_addr
, p
->opt
.prefixlen
, &addr_p
);
696 LIST_FOREACH(prefix
, cur
, ra
->route_prefixes
) {
698 r
= in_addr_prefix_intersect(AF_INET6
,
699 (const union in_addr_union
*) &cur
->opt
.in6_addr
,
701 (const union in_addr_union
*) &p
->opt
.in6_addr
,
708 if (cur
->opt
.prefixlen
== p
->opt
.prefixlen
) {
713 _cleanup_free_
char *addr_cur
= NULL
;
714 (void) in6_addr_prefix_to_string(&cur
->opt
.in6_addr
, cur
->opt
.prefixlen
, &addr_cur
);
715 return log_radv_errno(ra
, SYNTHETIC_ERRNO(EEXIST
),
716 "IPv6 route prefix %s conflicts with %s, ignoring.",
717 strna(addr_p
), strna(addr_cur
));
721 /* p and cur may be equivalent. First increment the reference counter. */
722 sd_radv_route_prefix_ref(p
);
724 /* Then, remove the old entry. */
725 LIST_REMOVE(prefix
, ra
->route_prefixes
, found
);
726 sd_radv_route_prefix_unref(found
);
728 /* Finally, add the new entry. */
729 LIST_APPEND(prefix
, ra
->route_prefixes
, p
);
731 log_radv(ra
, "Updated/replaced IPv6 route prefix %s (lifetime: %s)",
733 FORMAT_TIMESPAN(p
->lifetime_usec
, USEC_PER_SEC
));
735 /* The route prefix is new. Let's simply add it. */
737 sd_radv_route_prefix_ref(p
);
738 LIST_APPEND(prefix
, ra
->route_prefixes
, p
);
739 ra
->n_route_prefixes
++;
741 log_radv(ra
, "Added route prefix %s", strna(addr_p
));
744 if (ra
->state
== RADV_STATE_IDLE
)
747 if (ra
->ra_sent
== 0)
750 /* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */
751 r
= radv_send(ra
, NULL
, ra
->lifetime_usec
);
753 log_radv_errno(ra
, r
, "Unable to send Router Advertisement for added route prefix %s: %m",
756 log_radv(ra
, "Sent Router Advertisement for added route prefix %s.", strna(addr_p
));
761 int sd_radv_set_rdnss(sd_radv
*ra
, uint32_t lifetime
,
762 const struct in6_addr
*dns
, size_t n_dns
) {
763 _cleanup_free_
struct sd_radv_opt_dns
*opt_rdnss
= NULL
;
766 assert_return(ra
, -EINVAL
);
767 assert_return(n_dns
< 128, -EINVAL
);
769 if (!dns
|| n_dns
== 0) {
770 ra
->rdnss
= mfree(ra
->rdnss
);
776 len
= sizeof(struct sd_radv_opt_dns
) + sizeof(struct in6_addr
) * n_dns
;
778 opt_rdnss
= malloc0(len
);
782 opt_rdnss
->type
= RADV_OPT_RDNSS
;
783 opt_rdnss
->length
= len
/ 8;
784 opt_rdnss
->lifetime
= htobe32(lifetime
);
786 memcpy(opt_rdnss
+ 1, dns
, n_dns
* sizeof(struct in6_addr
));
788 free_and_replace(ra
->rdnss
, opt_rdnss
);
795 int sd_radv_set_dnssl(sd_radv
*ra
, uint32_t lifetime
,
796 char **search_list
) {
797 _cleanup_free_
struct sd_radv_opt_dns
*opt_dnssl
= NULL
;
802 assert_return(ra
, -EINVAL
);
804 if (strv_isempty(search_list
)) {
805 ra
->dnssl
= mfree(ra
->dnssl
);
809 STRV_FOREACH(s
, search_list
)
810 len
+= strlen(*s
) + 2;
812 len
= (sizeof(struct sd_radv_opt_dns
) + len
+ 7) & ~0x7;
814 opt_dnssl
= malloc0(len
);
818 opt_dnssl
->type
= RADV_OPT_DNSSL
;
819 opt_dnssl
->length
= len
/ 8;
820 opt_dnssl
->lifetime
= htobe32(lifetime
);
822 p
= (uint8_t *)(opt_dnssl
+ 1);
823 len
-= sizeof(struct sd_radv_opt_dns
);
825 STRV_FOREACH(s
, search_list
) {
828 r
= dns_name_to_wire_format(*s
, p
, len
, false);
839 free_and_replace(ra
->dnssl
, opt_dnssl
);
844 int sd_radv_prefix_new(sd_radv_prefix
**ret
) {
847 assert_return(ret
, -EINVAL
);
849 p
= new(sd_radv_prefix
, 1);
853 *p
= (sd_radv_prefix
) {
856 .opt
.type
= ND_OPT_PREFIX_INFORMATION
,
857 .opt
.length
= (sizeof(p
->opt
) - 1)/8 + 1,
860 /* RFC 4861, Section 6.2.1 */
861 .opt
.flags
= ND_OPT_PI_FLAG_ONLINK
|ND_OPT_PI_FLAG_AUTO
,
863 .lifetime_valid_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
864 .lifetime_preferred_usec
= RADV_DEFAULT_PREFERRED_LIFETIME_USEC
,
865 .valid_until
= USEC_INFINITY
,
866 .preferred_until
= USEC_INFINITY
,
873 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_prefix
, sd_radv_prefix
, mfree
);
875 int sd_radv_prefix_set_prefix(sd_radv_prefix
*p
, const struct in6_addr
*in6_addr
,
876 unsigned char prefixlen
) {
877 assert_return(p
, -EINVAL
);
878 assert_return(in6_addr
, -EINVAL
);
880 if (prefixlen
< 3 || prefixlen
> 128)
884 /* unusual but allowed, log it */
885 log_radv(NULL
, "Unusual prefix length %d greater than 64", prefixlen
);
887 p
->opt
.in6_addr
= *in6_addr
;
888 p
->opt
.prefixlen
= prefixlen
;
893 int sd_radv_prefix_get_prefix(sd_radv_prefix
*p
, struct in6_addr
*ret_in6_addr
,
894 unsigned char *ret_prefixlen
) {
895 assert_return(p
, -EINVAL
);
896 assert_return(ret_in6_addr
, -EINVAL
);
897 assert_return(ret_prefixlen
, -EINVAL
);
899 *ret_in6_addr
= p
->opt
.in6_addr
;
900 *ret_prefixlen
= p
->opt
.prefixlen
;
905 int sd_radv_prefix_set_onlink(sd_radv_prefix
*p
, int onlink
) {
906 assert_return(p
, -EINVAL
);
908 SET_FLAG(p
->opt
.flags
, ND_OPT_PI_FLAG_ONLINK
, onlink
);
913 int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix
*p
,
914 int address_autoconfiguration
) {
915 assert_return(p
, -EINVAL
);
917 SET_FLAG(p
->opt
.flags
, ND_OPT_PI_FLAG_AUTO
, address_autoconfiguration
);
922 int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix
*p
, uint64_t lifetime_usec
, uint64_t valid_until
) {
923 assert_return(p
, -EINVAL
);
925 p
->lifetime_valid_usec
= lifetime_usec
;
926 p
->valid_until
= valid_until
;
931 int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix
*p
, uint64_t lifetime_usec
, uint64_t valid_until
) {
932 assert_return(p
, -EINVAL
);
934 p
->lifetime_preferred_usec
= lifetime_usec
;
935 p
->preferred_until
= valid_until
;
940 int sd_radv_route_prefix_new(sd_radv_route_prefix
**ret
) {
941 sd_radv_route_prefix
*p
;
943 assert_return(ret
, -EINVAL
);
945 p
= new(sd_radv_route_prefix
, 1);
949 *p
= (sd_radv_route_prefix
) {
952 .opt
.type
= RADV_OPT_ROUTE_INFORMATION
,
953 .opt
.length
= DIV_ROUND_UP(sizeof(p
->opt
), 8),
956 .lifetime_usec
= RADV_DEFAULT_VALID_LIFETIME_USEC
,
957 .valid_until
= USEC_INFINITY
,
964 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_route_prefix
, sd_radv_route_prefix
, mfree
);
966 int sd_radv_route_prefix_set_prefix(sd_radv_route_prefix
*p
, const struct in6_addr
*in6_addr
,
967 unsigned char prefixlen
) {
968 assert_return(p
, -EINVAL
);
969 assert_return(in6_addr
, -EINVAL
);
975 /* unusual but allowed, log it */
976 log_radv(NULL
, "Unusual prefix length %u greater than 64", prefixlen
);
978 p
->opt
.in6_addr
= *in6_addr
;
979 p
->opt
.prefixlen
= prefixlen
;
984 int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix
*p
, uint64_t lifetime_usec
, uint64_t valid_until
) {
985 assert_return(p
, -EINVAL
);
987 p
->lifetime_usec
= lifetime_usec
;
988 p
->valid_until
= valid_until
;