Merge pull request #32345 from yuwata/sd-radv-send

sd-radv: introduce sd_radv_send(), and reset timer on sending unsplicited RA
This commit is contained in:
Luca Boccassi
2024-04-19 11:59:08 +02:00
committed by GitHub
2 changed files with 31 additions and 26 deletions
+30 -26
View File
@@ -279,11 +279,13 @@ static int radv_process_packet(sd_radv *ra, ICMP6Packet *packet) {
if (r < 0)
return r;
struct in6_addr src = {};
struct in6_addr src;
r = sd_ndisc_router_solicit_get_sender_address(rs, &src);
if (r < 0 && r != -ENODATA) /* null address is allowed */
if (r == -ENODATA) /* null address is allowed */
return sd_radv_send(ra); /* When an unsolicited RA, we need to also update timer. */
if (r < 0)
return log_radv_errno(ra, r, "Failed to get sender address of RS, ignoring: %m");
if (r >= 0 && in6_addr_equal(&src, &ra->ipv6ll))
if (in6_addr_equal(&src, &ra->ipv6ll))
/* This should be definitely caused by a misconfiguration. If we send RA to ourself, the
* kernel complains about that. Let's ignore the packet. */
return log_radv_errno(ra, SYNTHETIC_ERRNO(EADDRINUSE), "Received RS from the same interface, ignoring.");
@@ -314,24 +316,35 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
}
static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
usec_t min_timeout, max_timeout, time_now, timeout;
sd_radv *ra = ASSERT_PTR(userdata);
if (sd_radv_send(ra) < 0)
(void) sd_radv_stop(ra);
return 0;
}
int sd_radv_send(sd_radv *ra) {
usec_t min_timeout, max_timeout, time_now, timeout;
int r;
assert(s);
assert(ra->event);
assert_return(ra, -EINVAL);
assert_return(ra->event, -EINVAL);
assert_return(sd_radv_is_running(ra), -EINVAL);
assert(router_lifetime_is_valid(ra->lifetime_usec));
r = sd_event_now(ra->event, CLOCK_BOOTTIME, &time_now);
if (r < 0)
goto fail;
return r;
r = radv_send_router(ra, NULL);
if (r < 0)
log_radv_errno(ra, r, "Unable to send Router Advertisement, ignoring: %m");
return log_radv_errno(ra, r, "Unable to send Router Advertisement: %m");
ra->ra_sent++;
/* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
if (ra->ra_sent < RADV_MAX_INITIAL_RTR_ADVERTISEMENTS)
if (ra->ra_sent <= RADV_MAX_INITIAL_RTR_ADVERTISEMENTS)
max_timeout = RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC;
else
max_timeout = RADV_DEFAULT_MAX_TIMEOUT_USEC;
@@ -355,24 +368,15 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
assert(min_timeout <= max_timeout * 3 / 4);
timeout = min_timeout + random_u64_range(max_timeout - min_timeout);
log_radv(ra, "Next Router Advertisement in %s", FORMAT_TIMESPAN(timeout, USEC_PER_SEC));
log_radv(ra, "Sent unsolicited Router Advertisement. Next advertisement will be in %s.",
FORMAT_TIMESPAN(timeout, USEC_PER_SEC));
r = event_reset_time(ra->event, &ra->timeout_event_source,
CLOCK_BOOTTIME,
usec_add(time_now, timeout), MSEC_PER_SEC,
radv_timeout, ra,
ra->event_priority, "radv-timeout", true);
if (r < 0)
goto fail;
ra->ra_sent++;
return 0;
fail:
sd_radv_stop(ra);
return 0;
return event_reset_time(
ra->event, &ra->timeout_event_source,
CLOCK_BOOTTIME,
usec_add(time_now, timeout), MSEC_PER_SEC,
radv_timeout, ra,
ra->event_priority, "radv-timeout", true);
}
int sd_radv_stop(sd_radv *ra) {
+1
View File
@@ -48,6 +48,7 @@ sd_event *sd_radv_get_event(sd_radv *ra);
int sd_radv_start(sd_radv *ra);
int sd_radv_stop(sd_radv *ra);
int sd_radv_is_running(sd_radv *ra);
int sd_radv_send(sd_radv *ra);
int sd_radv_set_ifindex(sd_radv *ra, int interface_index);
int sd_radv_set_ifname(sd_radv *ra, const char *interface_name);