1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2017 Intel Corporation. All rights reserved.
6 #include <linux/ipv6.h>
7 #include <netinet/icmp6.h>
8 #include <netinet/in.h>
10 #include "sd-ndisc-protocol.h"
11 #include "sd-ndisc-router-solicit.h"
14 #include "alloc-util.h"
15 #include "event-util.h"
17 #include "icmp6-packet.h"
18 #include "icmp6-util.h"
19 #include "in-addr-util.h"
20 #include "memory-util.h"
21 #include "ndisc-option.h"
22 #include "ndisc-router-solicit-internal.h"
23 #include "network-common.h"
24 #include "radv-internal.h"
25 #include "random-util.h"
27 #include "socket-util.h"
28 #include "string-util.h"
30 int sd_radv_new(sd_radv
**ret
) {
31 _cleanup_(sd_radv_unrefp
) sd_radv
*ra
= NULL
;
33 assert_return(ret
, -EINVAL
);
42 .lifetime_usec
= RADV_DEFAULT_ROUTER_LIFETIME_USEC
,
50 int sd_radv_attach_event(sd_radv
*ra
, sd_event
*event
, int64_t priority
) {
53 assert_return(ra
, -EINVAL
);
54 assert_return(!ra
->event
, -EBUSY
);
57 ra
->event
= sd_event_ref(event
);
59 r
= sd_event_default(&ra
->event
);
64 ra
->event_priority
= priority
;
69 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
) {
86 return ra
->state
!= RADV_STATE_IDLE
;
89 static void radv_reset(sd_radv
*ra
) {
92 (void) event_source_disable(ra
->timeout_event_source
);
94 ra
->recv_event_source
= sd_event_source_disable_unref(ra
->recv_event_source
);
99 static sd_radv
*radv_free(sd_radv
*ra
) {
105 sd_event_source_unref(ra
->timeout_event_source
);
106 sd_radv_detach_event(ra
);
108 ra
->fd
= safe_close(ra
->fd
);
111 set_free(ra
->options
);
116 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv
, sd_radv
, radv_free
);
118 static bool router_lifetime_is_valid(usec_t lifetime_usec
) {
119 assert_cc(RADV_MAX_ROUTER_LIFETIME_USEC
<= UINT16_MAX
* USEC_PER_SEC
);
120 return lifetime_usec
== 0 ||
121 (lifetime_usec
>= RADV_MIN_ROUTER_LIFETIME_USEC
&&
122 lifetime_usec
<= RADV_MAX_ROUTER_LIFETIME_USEC
);
125 static int radv_send_router_on_stop(sd_radv
*ra
) {
126 static const struct nd_router_advert adv
= {
127 .nd_ra_type
= ND_ROUTER_ADVERT
,
130 _cleanup_set_free_ Set
*options
= NULL
;
131 struct ether_addr mac_addr
;
137 r
= sd_event_now(ra
->event
, CLOCK_BOOTTIME
, &time_now
);
141 /* On stop, we only send source link-layer address option. */
142 if (ndisc_option_get_mac(ra
->options
, SD_NDISC_OPTION_SOURCE_LL_ADDRESS
, &mac_addr
) >= 0) {
143 r
= ndisc_option_set_link_layer_address(&options
, SD_NDISC_OPTION_SOURCE_LL_ADDRESS
, &mac_addr
);
148 return ndisc_send(ra
->fd
, &IN6_ADDR_ALL_NODES_MULTICAST
, &adv
.nd_ra_hdr
, options
, time_now
);
151 static int radv_send_router(sd_radv
*ra
, const struct in6_addr
*dst
) {
154 struct nd_router_advert adv
= {
155 .nd_ra_type
= ND_ROUTER_ADVERT
,
156 .nd_ra_router_lifetime
= usec_to_be16_sec(ra
->lifetime_usec
),
157 .nd_ra_reachable
= usec_to_be32_msec(ra
->reachable_usec
),
158 .nd_ra_retransmit
= usec_to_be32_msec(ra
->retransmit_usec
),
163 r
= sd_event_now(ra
->event
, CLOCK_BOOTTIME
, &time_now
);
167 /* The nd_ra_curhoplimit and nd_ra_flags_reserved fields cannot specified with nd_ra_router_lifetime
168 * simultaneously in the structured initializer in the above. */
169 adv
.nd_ra_curhoplimit
= ra
->hop_limit
;
170 /* RFC 4191, Section 2.2,
171 * "...If the Router Lifetime is zero, the preference value MUST be set to (00) by the sender..." */
172 adv
.nd_ra_flags_reserved
= ra
->flags
| (ra
->lifetime_usec
> 0 ? (ra
->preference
<< 3) : 0);
174 return ndisc_send(ra
->fd
,
175 (dst
&& in6_addr_is_set(dst
)) ? dst
: &IN6_ADDR_ALL_NODES_MULTICAST
,
176 &adv
.nd_ra_hdr
, ra
->options
, time_now
);
179 static int radv_process_packet(sd_radv
*ra
, ICMP6Packet
*packet
) {
185 if (icmp6_packet_get_type(packet
) != ND_ROUTER_SOLICIT
)
186 return log_radv_errno(ra
, SYNTHETIC_ERRNO(EBADMSG
), "Received ICMP6 packet with unexpected type, ignoring.");
188 _cleanup_(sd_ndisc_router_solicit_unrefp
) sd_ndisc_router_solicit
*rs
= NULL
;
189 rs
= ndisc_router_solicit_new(packet
);
191 return log_oom_debug();
193 r
= ndisc_router_solicit_parse(ra
, rs
);
198 r
= sd_ndisc_router_solicit_get_sender_address(rs
, &src
);
199 if (r
== -ENODATA
) /* null address is allowed */
200 return sd_radv_send(ra
); /* When an unsolicited RA, we need to also update timer. */
202 return log_radv_errno(ra
, r
, "Failed to get sender address of RS, ignoring: %m");
203 if (in6_addr_equal(&src
, &ra
->ipv6ll
))
204 /* This should be definitely caused by a misconfiguration. If we send RA to ourself, the
205 * kernel complains about that. Let's ignore the packet. */
206 return log_radv_errno(ra
, SYNTHETIC_ERRNO(EADDRINUSE
), "Received RS from the same interface, ignoring.");
208 r
= radv_send_router(ra
, &src
);
210 return log_radv_errno(ra
, r
, "Unable to send solicited Router Advertisement to %s, ignoring: %m", IN6_ADDR_TO_STRING(&src
));
212 log_radv(ra
, "Sent solicited Router Advertisement to %s.", IN6_ADDR_TO_STRING(&src
));
216 static int radv_recv(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
217 _cleanup_(icmp6_packet_unrefp
) ICMP6Packet
*packet
= NULL
;
218 sd_radv
*ra
= ASSERT_PTR(userdata
);
223 r
= icmp6_packet_receive(fd
, &packet
);
225 log_radv_errno(ra
, r
, "Failed to receive ICMPv6 packet, ignoring: %m");
229 (void) radv_process_packet(ra
, packet
);
233 static int radv_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
234 sd_radv
*ra
= ASSERT_PTR(userdata
);
236 if (sd_radv_send(ra
) < 0)
237 (void) sd_radv_stop(ra
);
242 int sd_radv_send(sd_radv
*ra
) {
243 usec_t min_timeout
, max_timeout
, time_now
, timeout
;
246 assert_return(ra
, -EINVAL
);
247 assert_return(ra
->event
, -EINVAL
);
248 assert_return(sd_radv_is_running(ra
), -EINVAL
);
249 assert(router_lifetime_is_valid(ra
->lifetime_usec
));
251 r
= sd_event_now(ra
->event
, CLOCK_BOOTTIME
, &time_now
);
255 r
= radv_send_router(ra
, NULL
);
257 return log_radv_errno(ra
, r
, "Unable to send Router Advertisement: %m");
261 /* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
262 if (ra
->ra_sent
<= RADV_MAX_INITIAL_RTR_ADVERTISEMENTS
)
263 max_timeout
= RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC
;
265 max_timeout
= RADV_DEFAULT_MAX_TIMEOUT_USEC
;
267 /* RFC 4861, Section 6.2.1, lifetime must be at least MaxRtrAdvInterval,
268 * so lower the interval here */
269 if (ra
->lifetime_usec
> 0)
270 max_timeout
= MIN(max_timeout
, ra
->lifetime_usec
);
272 if (max_timeout
>= 9 * USEC_PER_SEC
)
273 min_timeout
= max_timeout
/ 3;
275 min_timeout
= max_timeout
* 3 / 4;
277 /* RFC 4861, Section 6.2.1.
278 * MaxRtrAdvInterval MUST be no less than 4 seconds and no greater than 1800 seconds.
279 * MinRtrAdvInterval MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval. */
280 assert(max_timeout
>= RADV_MIN_MAX_TIMEOUT_USEC
);
281 assert(max_timeout
<= RADV_MAX_MAX_TIMEOUT_USEC
);
282 assert(min_timeout
>= RADV_MIN_MIN_TIMEOUT_USEC
);
283 assert(min_timeout
<= max_timeout
* 3 / 4);
285 timeout
= min_timeout
+ random_u64_range(max_timeout
- min_timeout
);
286 log_radv(ra
, "Sent unsolicited Router Advertisement. Next advertisement will be in %s.",
287 FORMAT_TIMESPAN(timeout
, USEC_PER_SEC
));
289 return event_reset_time(
290 ra
->event
, &ra
->timeout_event_source
,
292 usec_add(time_now
, timeout
), MSEC_PER_SEC
,
294 ra
->event_priority
, "radv-timeout", true);
297 int sd_radv_stop(sd_radv
*ra
) {
300 if (!sd_radv_is_running(ra
))
301 return 0; /* Already stopped. */
303 log_radv(ra
, "Stopping IPv6 Router Advertisement daemon");
305 /* RFC 4861, Section 6.2.5:
306 * the router SHOULD transmit one or more (but not more than MAX_FINAL_RTR_ADVERTISEMENTS) final
307 * multicast Router Advertisements on the interface with a Router Lifetime field of zero. */
308 r
= radv_send_router_on_stop(ra
);
310 log_radv_errno(ra
, r
, "Unable to send last Router Advertisement with router lifetime set to zero, ignoring: %m");
313 ra
->fd
= safe_close(ra
->fd
);
314 ra
->state
= RADV_STATE_IDLE
;
319 static int radv_setup_recv_event(sd_radv
*ra
) {
324 assert(ra
->ifindex
> 0);
326 _cleanup_close_
int fd
= -EBADF
;
327 fd
= icmp6_bind(ra
->ifindex
, /* is_router = */ true);
331 _cleanup_(sd_event_source_unrefp
) sd_event_source
*s
= NULL
;
332 r
= sd_event_add_io(ra
->event
, &s
, fd
, EPOLLIN
, radv_recv
, ra
);
336 r
= sd_event_source_set_priority(s
, ra
->event_priority
);
340 (void) sd_event_source_set_description(s
, "radv-receive-message");
342 ra
->fd
= TAKE_FD(fd
);
343 ra
->recv_event_source
= TAKE_PTR(s
);
347 int sd_radv_start(sd_radv
*ra
) {
350 assert_return(ra
, -EINVAL
);
351 assert_return(ra
->event
, -EINVAL
);
352 assert_return(ra
->ifindex
> 0, -EINVAL
);
354 if (sd_radv_is_running(ra
))
355 return 0; /* Already started. */
357 r
= radv_setup_recv_event(ra
);
361 r
= event_reset_time(ra
->event
, &ra
->timeout_event_source
,
365 ra
->event_priority
, "radv-timeout", true);
369 ra
->state
= RADV_STATE_ADVERTISING
;
371 log_radv(ra
, "Started IPv6 Router Advertisement daemon");
381 int sd_radv_set_ifindex(sd_radv
*ra
, int ifindex
) {
382 assert_return(ra
, -EINVAL
);
383 assert_return(!sd_radv_is_running(ra
), -EBUSY
);
384 assert_return(ifindex
> 0, -EINVAL
);
386 ra
->ifindex
= ifindex
;
390 int sd_radv_set_ifname(sd_radv
*ra
, const char *ifname
) {
391 assert_return(ra
, -EINVAL
);
392 assert_return(ifname
, -EINVAL
);
394 if (!ifname_valid_full(ifname
, IFNAME_VALID_ALTERNATIVE
))
397 return free_and_strdup(&ra
->ifname
, ifname
);
400 int sd_radv_get_ifname(sd_radv
*ra
, const char **ret
) {
403 assert_return(ra
, -EINVAL
);
405 r
= get_ifname(ra
->ifindex
, &ra
->ifname
);
415 int sd_radv_set_link_local_address(sd_radv
*ra
, const struct in6_addr
*addr
) {
416 assert_return(ra
, -EINVAL
);
417 assert_return(!addr
|| in6_addr_is_link_local(addr
), -EINVAL
);
427 /* Managing RA header. */
429 int sd_radv_set_hop_limit(sd_radv
*ra
, uint8_t hop_limit
) {
430 assert_return(ra
, -EINVAL
);
432 ra
->hop_limit
= hop_limit
;
436 int sd_radv_set_reachable_time(sd_radv
*ra
, uint64_t usec
) {
437 assert_return(ra
, -EINVAL
);
439 ra
->reachable_usec
= usec
;
443 int sd_radv_set_retransmit(sd_radv
*ra
, uint64_t usec
) {
444 assert_return(ra
, -EINVAL
);
446 ra
->retransmit_usec
= usec
;
450 int sd_radv_set_router_lifetime(sd_radv
*ra
, uint64_t usec
) {
451 assert_return(ra
, -EINVAL
);
453 if (!router_lifetime_is_valid(usec
))
456 ra
->lifetime_usec
= usec
;
460 int sd_radv_set_managed_information(sd_radv
*ra
, int b
) {
461 assert_return(ra
, -EINVAL
);
463 SET_FLAG(ra
->flags
, ND_RA_FLAG_MANAGED
, b
);
467 int sd_radv_set_other_information(sd_radv
*ra
, int b
) {
468 assert_return(ra
, -EINVAL
);
470 SET_FLAG(ra
->flags
, ND_RA_FLAG_OTHER
, b
);
474 int sd_radv_set_preference(sd_radv
*ra
, uint8_t preference
) {
475 assert_return(ra
, -EINVAL
);
476 assert_return(IN_SET(preference
,
477 SD_NDISC_PREFERENCE_LOW
,
478 SD_NDISC_PREFERENCE_MEDIUM
,
479 SD_NDISC_PREFERENCE_HIGH
), -EINVAL
);
481 ra
->preference
= preference
;
485 /* Managing options. */
487 int sd_radv_set_mac(sd_radv
*ra
, const struct ether_addr
*mac_addr
) {
488 assert_return(ra
, -EINVAL
);
490 return ndisc_option_set_link_layer_address(&ra
->options
, SD_NDISC_OPTION_SOURCE_LL_ADDRESS
, mac_addr
);
493 void sd_radv_unset_mac(sd_radv
*ra
) {
497 ndisc_option_remove_by_type(ra
->options
, SD_NDISC_OPTION_SOURCE_LL_ADDRESS
);
500 int sd_radv_add_prefix(
502 const struct in6_addr
*prefix
,
505 uint64_t valid_lifetime_usec
,
506 uint64_t preferred_lifetime_usec
,
507 uint64_t valid_until
,
508 uint64_t preferred_until
) {
510 assert_return(ra
, -EINVAL
);
511 assert_return(prefix
, -EINVAL
);
513 sd_ndisc_option
*opt
;
514 SET_FOREACH(opt
, ra
->options
) {
515 if (opt
->type
!= SD_NDISC_OPTION_PREFIX_INFORMATION
)
518 if (!in6_addr_prefix_intersect(&opt
->prefix
.address
, opt
->prefix
.prefixlen
, prefix
, prefixlen
))
519 continue; /* no intersection */
521 if (opt
->prefix
.prefixlen
== prefixlen
)
522 break; /* same prefix */
524 return log_radv_errno(ra
, SYNTHETIC_ERRNO(EEXIST
),
525 "IPv6 prefix %s conflicts with %s, ignoring.",
526 IN6_ADDR_PREFIX_TO_STRING(prefix
, prefixlen
),
527 IN6_ADDR_PREFIX_TO_STRING(&opt
->prefix
.address
, opt
->prefix
.prefixlen
));
530 return ndisc_option_set_prefix(
536 preferred_lifetime_usec
,
541 void sd_radv_remove_prefix(
543 const struct in6_addr
*prefix
,
549 ndisc_option_remove(ra
->options
,
551 .type
= SD_NDISC_OPTION_PREFIX_INFORMATION
,
552 .prefix
.prefixlen
= prefixlen
,
553 .prefix
.address
= *prefix
,
557 int sd_radv_set_mtu(sd_radv
*ra
, uint32_t mtu
) {
558 assert_return(ra
, -EINVAL
);
559 assert_return(mtu
>= IPV6_MIN_MTU
, -EINVAL
);
561 return ndisc_option_set_mtu(&ra
->options
, mtu
);
564 void sd_radv_unset_mtu(sd_radv
*ra
) {
568 ndisc_option_remove_by_type(ra
->options
, SD_NDISC_OPTION_MTU
);
571 int sd_radv_set_home_agent(sd_radv
*ra
, uint16_t preference
, uint64_t lifetime_usec
, uint64_t valid_until
) {
572 assert_return(ra
, -EINVAL
);
574 ra
->flags
|= ND_RA_FLAG_HOME_AGENT
;
575 return ndisc_option_set_home_agent(&ra
->options
, preference
, lifetime_usec
, valid_until
);
578 void sd_radv_unset_home_agent(sd_radv
*ra
) {
582 ra
->flags
&= ~ND_RA_FLAG_HOME_AGENT
;
583 ndisc_option_remove_by_type(ra
->options
, SD_NDISC_OPTION_HOME_AGENT
);
586 int sd_radv_add_route(
588 const struct in6_addr
*prefix
,
591 uint64_t lifetime_usec
,
592 uint64_t valid_until
) {
594 assert_return(ra
, -EINVAL
);
595 assert_return(prefix
, -EINVAL
);
597 return ndisc_option_set_route(
606 void sd_radv_remove_route(
608 const struct in6_addr
*prefix
,
614 ndisc_option_remove(ra
->options
,
616 .type
= SD_NDISC_OPTION_ROUTE_INFORMATION
,
617 .route
.prefixlen
= prefixlen
,
618 .route
.address
= *prefix
,
622 int sd_radv_add_rdnss(
625 const struct in6_addr
*dns
,
626 uint64_t lifetime_usec
,
627 uint64_t valid_until
) {
629 assert_return(ra
, -EINVAL
);
630 assert_return(dns
, -EINVAL
);
632 return ndisc_option_set_rdnss(
640 void sd_radv_clear_rdnss(sd_radv
*ra
) {
644 sd_ndisc_option
*opt
;
645 SET_FOREACH(opt
, ra
->options
)
646 if (opt
->type
== SD_NDISC_OPTION_RDNSS
)
647 ndisc_option_remove(ra
->options
, opt
);
650 int sd_radv_add_dnssl(
652 char * const *domains
,
653 uint64_t lifetime_usec
,
654 uint64_t valid_until
) {
656 assert_return(ra
, -EINVAL
);
658 return ndisc_option_set_dnssl(
665 void sd_radv_clear_dnssl(sd_radv
*ra
) {
669 sd_ndisc_option
*opt
;
670 SET_FOREACH(opt
, ra
->options
)
671 if (opt
->type
== SD_NDISC_OPTION_DNSSL
)
672 ndisc_option_remove(ra
->options
, opt
);
675 int sd_radv_set_captive_portal(sd_radv
*ra
, const char *portal
) {
676 assert_return(ra
, -EINVAL
);
677 assert_return(portal
, -EINVAL
);
679 return ndisc_option_set_captive_portal(&ra
->options
, portal
);
682 void sd_radv_unset_captive_portal(sd_radv
*ra
) {
686 ndisc_option_remove_by_type(ra
->options
, SD_NDISC_OPTION_CAPTIVE_PORTAL
);
689 int sd_radv_add_prefix64(
691 const struct in6_addr
*prefix
,
693 uint64_t lifetime_usec
,
694 uint64_t valid_until
) {
696 assert_return(ra
, -EINVAL
);
697 assert_return(prefix
, -EINVAL
);
699 return ndisc_option_set_prefix64(
707 void sd_radv_remove_prefix64(
709 const struct in6_addr
*prefix
,
715 ndisc_option_remove(ra
->options
,
717 .type
= SD_NDISC_OPTION_PREF64
,
718 .prefix64
.prefixlen
= prefixlen
,
719 .prefix64
.prefix
= *prefix
,