Closes #31402.
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>UseReachableTime=</varname></term>
+ <listitem>
+ <para>Takes a boolean. When true, the reachable time received in the Router Advertisement will be
+ set on the interface receiving the advertisement. It is used as the base timespan of the validity
+ of a neighbor entry. Defaults to true.</para>
+
+ <xi:include href="version-info.xml" xpointer="v256"/>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>UseRetransmissionTime=</varname></term>
<listitem>
return 0;
}
+static int ndisc_router_process_reachable_time(Link *link, sd_ndisc_router *rt) {
+ usec_t reachable_time, msec;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(rt);
+
+ if (!link->network->ipv6_accept_ra_use_reachable_time)
+ return 0;
+
+ /* Ignore the reachable time field of the RA header if the lifetime is zero. */
+ r = sd_ndisc_router_get_lifetime(rt, NULL);
+ if (r <= 0)
+ return r;
+
+ r = sd_ndisc_router_get_reachable_time(rt, &reachable_time);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to get reachable time from RA: %m");
+
+ /* 0 is the unspecified value and must not be set (see RFC4861, 6.3.4) */
+ if (!timestamp_is_set(reachable_time))
+ return 0;
+
+ msec = DIV_ROUND_UP(reachable_time, USEC_PER_MSEC);
+ if (msec <= 0 || msec > UINT32_MAX) {
+ log_link_debug(link, "Failed to get reachable time from RA - out of range (%"PRIu64"), ignoring", msec);
+ return 0;
+ }
+
+ /* Set the reachable time for Neighbor Solicitations. */
+ r = sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "base_reachable_time_ms", (uint32_t) msec);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to apply neighbor reachable time (%"PRIu64"), ignoring: %m", msec);
+
+ return 0;
+}
+
static int ndisc_router_process_retransmission_time(Link *link, sd_ndisc_router *rt) {
usec_t retrans_time, msec;
int r;
if (r < 0)
return r;
+ r = ndisc_router_process_reachable_time(link, rt);
+ if (r < 0)
+ return r;
+
r = ndisc_router_process_retransmission_time(link, rt);
if (r < 0)
return r;
IPv6AcceptRA.UseDomains, config_parse_ipv6_accept_ra_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains)
IPv6AcceptRA.UseMTU, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_mtu)
IPv6AcceptRA.UseHopLimit, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_hop_limit)
+IPv6AcceptRA.UseReachableTime, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_reachable_time)
IPv6AcceptRA.UseRetransmissionTime, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_retransmission_time)
IPv6AcceptRA.UseICMP6RateLimit, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_icmp6_ratelimit)
IPv6AcceptRA.DHCPv6Client, config_parse_ipv6_accept_ra_start_dhcp6_client, 0, offsetof(Network, ipv6_accept_ra_start_dhcp6_client)
.ipv6_accept_ra_use_onlink_prefix = true,
.ipv6_accept_ra_use_mtu = true,
.ipv6_accept_ra_use_hop_limit = true,
+ .ipv6_accept_ra_use_reachable_time = true,
.ipv6_accept_ra_use_retransmission_time = true,
.ipv6_accept_ra_use_icmp6_ratelimit = true,
.ipv6_accept_ra_route_table = RT_TABLE_MAIN,
bool ipv6_accept_ra_use_onlink_prefix;
bool ipv6_accept_ra_use_mtu;
bool ipv6_accept_ra_use_hop_limit;
+ bool ipv6_accept_ra_use_reachable_time;
bool ipv6_accept_ra_use_retransmission_time;
bool ipv6_accept_ra_use_icmp6_ratelimit;
bool ipv6_accept_ra_quickack;