mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Merge pull request #21072 from yuwata/network-address-lifetime
network: address: use usec_t for handling lifetime
This commit is contained in:
commit
f45fb83996
@ -67,8 +67,8 @@ int address_new(Address **ret) {
|
|||||||
*address = (Address) {
|
*address = (Address) {
|
||||||
.family = AF_UNSPEC,
|
.family = AF_UNSPEC,
|
||||||
.scope = RT_SCOPE_UNIVERSE,
|
.scope = RT_SCOPE_UNIVERSE,
|
||||||
.cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME,
|
.lifetime_valid_usec = USEC_INFINITY,
|
||||||
.cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME,
|
.lifetime_preferred_usec = USEC_INFINITY,
|
||||||
.set_broadcast = -1,
|
.set_broadcast = -1,
|
||||||
.duplicate_address_detection = ADDRESS_FAMILY_IPV6,
|
.duplicate_address_detection = ADDRESS_FAMILY_IPV6,
|
||||||
};
|
};
|
||||||
@ -224,6 +224,41 @@ static bool address_may_set_broadcast(const Address *a, const Link *link) {
|
|||||||
return !streq_ptr(link->kind, "wireguard");
|
return !streq_ptr(link->kind, "wireguard");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ifa_cacheinfo *address_set_cinfo(const Address *a, struct ifa_cacheinfo *cinfo) {
|
||||||
|
usec_t now_usec;
|
||||||
|
|
||||||
|
assert(a);
|
||||||
|
assert(cinfo);
|
||||||
|
|
||||||
|
now_usec = now(clock_boottime_or_monotonic());
|
||||||
|
|
||||||
|
*cinfo = (struct ifa_cacheinfo) {
|
||||||
|
.ifa_valid = MIN(usec_sub_unsigned(a->lifetime_valid_usec, now_usec) / USEC_PER_SEC, UINT32_MAX),
|
||||||
|
.ifa_prefered = MIN(usec_sub_unsigned(a->lifetime_preferred_usec, now_usec) / USEC_PER_SEC, UINT32_MAX),
|
||||||
|
};
|
||||||
|
|
||||||
|
return cinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void address_set_lifetime(Address *a, const struct ifa_cacheinfo *cinfo) {
|
||||||
|
usec_t now_usec;
|
||||||
|
|
||||||
|
assert(a);
|
||||||
|
assert(cinfo);
|
||||||
|
|
||||||
|
now_usec = now(clock_boottime_or_monotonic());
|
||||||
|
|
||||||
|
if (cinfo->ifa_valid == UINT32_MAX)
|
||||||
|
a->lifetime_valid_usec = USEC_INFINITY;
|
||||||
|
else
|
||||||
|
a->lifetime_valid_usec = usec_add(cinfo->ifa_valid * USEC_PER_SEC, now_usec);
|
||||||
|
|
||||||
|
if (cinfo->ifa_prefered == UINT32_MAX)
|
||||||
|
a->lifetime_preferred_usec = USEC_INFINITY;
|
||||||
|
else
|
||||||
|
a->lifetime_preferred_usec = usec_add(cinfo->ifa_prefered * USEC_PER_SEC, now_usec);
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t address_prefix(const Address *a) {
|
static uint32_t address_prefix(const Address *a) {
|
||||||
assert(a);
|
assert(a);
|
||||||
|
|
||||||
@ -553,16 +588,16 @@ int manager_has_address(Manager *manager, int family, const union in_addr_union
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* format_lifetime(char *buf, size_t l, uint32_t lifetime) {
|
const char* format_lifetime(char *buf, size_t l, usec_t lifetime_usec) {
|
||||||
assert(buf);
|
assert(buf);
|
||||||
assert(l > 4);
|
assert(l > 4);
|
||||||
|
|
||||||
if (lifetime == CACHE_INFO_INFINITY_LIFE_TIME)
|
if (lifetime_usec == USEC_INFINITY)
|
||||||
return "forever";
|
return "forever";
|
||||||
|
|
||||||
sprintf(buf, "for ");
|
sprintf(buf, "for ");
|
||||||
/* format_timespan() never fails */
|
/* format_timespan() never fails */
|
||||||
assert_se(format_timespan(buf + 4, l - 4, lifetime * USEC_PER_SEC, USEC_PER_SEC));
|
assert_se(format_timespan(buf + 4, l - 4, usec_sub_unsigned(lifetime_usec, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,8 +621,8 @@ static void log_address_debug(const Address *address, const char *str, const Lin
|
|||||||
log_link_debug(link, "%s %s address (%s): %s%s%s/%u (valid %s, preferred %s), flags: %s",
|
log_link_debug(link, "%s %s address (%s): %s%s%s/%u (valid %s, preferred %s), flags: %s",
|
||||||
str, strna(network_config_source_to_string(address->source)), strna(state),
|
str, strna(network_config_source_to_string(address->source)), strna(state),
|
||||||
strnull(addr), peer ? " peer " : "", strempty(peer), address->prefixlen,
|
strnull(addr), peer ? " peer " : "", strempty(peer), address->prefixlen,
|
||||||
FORMAT_LIFETIME(address->cinfo.ifa_valid),
|
FORMAT_LIFETIME(address->lifetime_valid_usec),
|
||||||
FORMAT_LIFETIME(address->cinfo.ifa_prefered),
|
FORMAT_LIFETIME(address->lifetime_preferred_usec),
|
||||||
strna(flags_str));
|
strna(flags_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,7 +719,7 @@ bool link_address_is_dynamic(const Link *link, const Address *address) {
|
|||||||
assert(link);
|
assert(link);
|
||||||
assert(address);
|
assert(address);
|
||||||
|
|
||||||
if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
|
if (address->lifetime_preferred_usec != USEC_INFINITY)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Even when the address is leased from a DHCP server, networkd assign the address
|
/* Even when the address is leased from a DHCP server, networkd assign the address
|
||||||
@ -983,7 +1018,8 @@ static int address_configure(
|
|||||||
return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m");
|
return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
|
r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO,
|
||||||
|
address_set_cinfo(address, &(struct ifa_cacheinfo) {}));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
|
return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
|
||||||
|
|
||||||
@ -1192,6 +1228,7 @@ int request_process_address(Request *req) {
|
|||||||
|
|
||||||
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||||
_cleanup_(address_freep) Address *tmp = NULL;
|
_cleanup_(address_freep) Address *tmp = NULL;
|
||||||
|
struct ifa_cacheinfo cinfo;
|
||||||
Link *link = NULL;
|
Link *link = NULL;
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
Address *address = NULL;
|
Address *address = NULL;
|
||||||
@ -1326,7 +1363,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &tmp->cinfo);
|
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo);
|
||||||
if (r < 0 && r != -ENODATA) {
|
if (r < 0 && r != -ENODATA) {
|
||||||
log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m");
|
log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
@ -1340,10 +1377,11 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||||||
/* update flags and etc. */
|
/* update flags and etc. */
|
||||||
address->flags = tmp->flags;
|
address->flags = tmp->flags;
|
||||||
address->scope = tmp->scope;
|
address->scope = tmp->scope;
|
||||||
address->cinfo = tmp->cinfo;
|
address_set_lifetime(address, &cinfo);
|
||||||
address_enter_configured(address);
|
address_enter_configured(address);
|
||||||
log_address_debug(address, "Received updated", link);
|
log_address_debug(address, "Received updated", link);
|
||||||
} else {
|
} else {
|
||||||
|
address_set_lifetime(tmp, &cinfo);
|
||||||
address_enter_configured(tmp);
|
address_enter_configured(tmp);
|
||||||
log_address_debug(tmp, "Received new", link);
|
log_address_debug(tmp, "Received new", link);
|
||||||
|
|
||||||
@ -1602,7 +1640,7 @@ int config_parse_lifetime(
|
|||||||
|
|
||||||
Network *network = userdata;
|
Network *network = userdata;
|
||||||
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
|
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
|
||||||
uint32_t k;
|
usec_t k;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
@ -1622,7 +1660,7 @@ int config_parse_lifetime(
|
|||||||
|
|
||||||
/* We accept only "forever", "infinity", empty, or "0". */
|
/* We accept only "forever", "infinity", empty, or "0". */
|
||||||
if (STR_IN_SET(rvalue, "forever", "infinity", ""))
|
if (STR_IN_SET(rvalue, "forever", "infinity", ""))
|
||||||
k = CACHE_INFO_INFINITY_LIFE_TIME;
|
k = USEC_INFINITY;
|
||||||
else if (streq(rvalue, "0"))
|
else if (streq(rvalue, "0"))
|
||||||
k = 0;
|
k = 0;
|
||||||
else {
|
else {
|
||||||
@ -1631,7 +1669,7 @@ int config_parse_lifetime(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
n->cinfo.ifa_prefered = k;
|
n->lifetime_preferred_usec = k;
|
||||||
TAKE_PTR(n);
|
TAKE_PTR(n);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
#include "in-addr-util.h"
|
#include "in-addr-util.h"
|
||||||
#include "networkd-link.h"
|
#include "networkd-link.h"
|
||||||
#include "networkd-util.h"
|
#include "networkd-util.h"
|
||||||
|
#include "time-util.h"
|
||||||
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
|
|
||||||
|
|
||||||
typedef struct Address Address;
|
typedef struct Address Address;
|
||||||
typedef struct Manager Manager;
|
typedef struct Manager Manager;
|
||||||
@ -37,11 +36,15 @@ struct Address {
|
|||||||
|
|
||||||
int set_broadcast;
|
int set_broadcast;
|
||||||
struct in_addr broadcast;
|
struct in_addr broadcast;
|
||||||
struct ifa_cacheinfo cinfo;
|
|
||||||
|
|
||||||
union in_addr_union in_addr;
|
union in_addr_union in_addr;
|
||||||
union in_addr_union in_addr_peer;
|
union in_addr_union in_addr_peer;
|
||||||
|
|
||||||
|
/* These are absolute points in time, and NOT timespans/durations.
|
||||||
|
* Must be specified with clock_boottime_or_monotonic(). */
|
||||||
|
usec_t lifetime_valid_usec;
|
||||||
|
usec_t lifetime_preferred_usec;
|
||||||
|
|
||||||
bool scope_set:1;
|
bool scope_set:1;
|
||||||
bool ip_masquerade_done:1;
|
bool ip_masquerade_done:1;
|
||||||
AddressFamily duplicate_address_detection;
|
AddressFamily duplicate_address_detection;
|
||||||
@ -51,7 +54,7 @@ struct Address {
|
|||||||
address_ready_callback_t callback;
|
address_ready_callback_t callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* format_lifetime(char *buf, size_t l, uint32_t lifetime) _warn_unused_result_;
|
const char* format_lifetime(char *buf, size_t l, usec_t lifetime_usec) _warn_unused_result_;
|
||||||
/* Note: the lifetime of the compound literal is the immediately surrounding block,
|
/* Note: the lifetime of the compound literal is the immediately surrounding block,
|
||||||
* see C11 §6.5.2.5, and
|
* see C11 §6.5.2.5, and
|
||||||
* https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */
|
* https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */
|
||||||
|
@ -841,10 +841,10 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
|
|||||||
|
|
||||||
static int dhcp4_request_address(Link *link, bool announce) {
|
static int dhcp4_request_address(Link *link, bool announce) {
|
||||||
_cleanup_(address_freep) Address *addr = NULL;
|
_cleanup_(address_freep) Address *addr = NULL;
|
||||||
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
|
|
||||||
struct in_addr address, netmask, server;
|
struct in_addr address, netmask, server;
|
||||||
unsigned prefixlen;
|
unsigned prefixlen;
|
||||||
Address *existing;
|
Address *existing;
|
||||||
|
usec_t lifetime_usec;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
@ -864,10 +864,15 @@ static int dhcp4_request_address(Link *link, bool announce) {
|
|||||||
return log_link_debug_errno(link, r, "DHCP error: failed to get DHCP server IP address: %m");
|
return log_link_debug_errno(link, r, "DHCP error: failed to get DHCP server IP address: %m");
|
||||||
|
|
||||||
if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
|
if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
|
||||||
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
|
uint32_t lifetime_sec;
|
||||||
|
|
||||||
|
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
|
return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
|
||||||
}
|
|
||||||
|
lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now(clock_boottime_or_monotonic()));
|
||||||
|
} else
|
||||||
|
lifetime_usec = USEC_INFINITY;
|
||||||
|
|
||||||
prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
|
prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
|
||||||
|
|
||||||
@ -908,8 +913,8 @@ static int dhcp4_request_address(Link *link, bool announce) {
|
|||||||
addr->provider.in = server;
|
addr->provider.in = server;
|
||||||
addr->family = AF_INET;
|
addr->family = AF_INET;
|
||||||
addr->in_addr.in.s_addr = address.s_addr;
|
addr->in_addr.in.s_addr = address.s_addr;
|
||||||
addr->cinfo.ifa_prefered = lifetime;
|
addr->lifetime_preferred_usec = lifetime_usec;
|
||||||
addr->cinfo.ifa_valid = lifetime;
|
addr->lifetime_valid_usec = lifetime_usec;
|
||||||
addr->prefixlen = prefixlen;
|
addr->prefixlen = prefixlen;
|
||||||
if (prefixlen <= 30)
|
if (prefixlen <= 30)
|
||||||
addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
|
addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
|
||||||
@ -1698,7 +1703,6 @@ int config_parse_dhcp_fallback_lease_lifetime(
|
|||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
Network *network = userdata;
|
Network *network = userdata;
|
||||||
uint32_t k;
|
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section);
|
assert(section);
|
||||||
@ -1712,15 +1716,13 @@ int config_parse_dhcp_fallback_lease_lifetime(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We accept only "forever" or "infinity". */
|
/* We accept only "forever" or "infinity". */
|
||||||
if (STR_IN_SET(rvalue, "forever", "infinity"))
|
if (!STR_IN_SET(rvalue, "forever", "infinity")) {
|
||||||
k = CACHE_INFO_INFINITY_LIFE_TIME;
|
|
||||||
else {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||||
"Invalid LeaseLifetime= value, ignoring: %s", rvalue);
|
"Invalid LeaseLifetime= value, ignoring: %s", rvalue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
network->dhcp_fallback_lease_lifetime = k;
|
network->dhcp_fallback_lease_lifetime = UINT32_MAX;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ bool link_dhcp6_pd_is_enabled(Link *link) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
|
static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
|
||||||
uint32_t lifetime_preferred, lifetime_valid;
|
uint32_t lifetime_preferred_sec, lifetime_valid_sec;
|
||||||
struct in6_addr pd_prefix;
|
struct in6_addr pd_prefix;
|
||||||
uint8_t pd_prefix_len;
|
uint8_t pd_prefix_len;
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
|
|||||||
|
|
||||||
sd_dhcp6_lease_reset_pd_prefix_iter(lease);
|
sd_dhcp6_lease_reset_pd_prefix_iter(lease);
|
||||||
|
|
||||||
return sd_dhcp6_lease_get_pd(lease, &pd_prefix, &pd_prefix_len, &lifetime_preferred, &lifetime_valid) >= 0;
|
return sd_dhcp6_lease_get_pd(lease, &pd_prefix, &pd_prefix_len, &lifetime_preferred_sec, &lifetime_valid_sec) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void link_remove_dhcp6_pd_prefix(Link *link, const struct in6_addr *prefix) {
|
static void link_remove_dhcp6_pd_prefix(Link *link, const struct in6_addr *prefix) {
|
||||||
@ -287,7 +287,7 @@ static int dhcp6_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, usec_t timestamp_usec, uint32_t lifetime_sec) {
|
static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, usec_t lifetime_usec) {
|
||||||
_cleanup_(route_freep) Route *route = NULL;
|
_cleanup_(route_freep) Route *route = NULL;
|
||||||
Route *existing;
|
Route *existing;
|
||||||
int r;
|
int r;
|
||||||
@ -309,7 +309,7 @@ static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, use
|
|||||||
route->dst_prefixlen = 64;
|
route->dst_prefixlen = 64;
|
||||||
route->protocol = RTPROT_DHCP;
|
route->protocol = RTPROT_DHCP;
|
||||||
route->priority = link->network->dhcp6_pd_route_metric;
|
route->priority = link->network->dhcp6_pd_route_metric;
|
||||||
route->lifetime = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
|
route->lifetime_usec = lifetime_usec;
|
||||||
|
|
||||||
if (route_get(NULL, link, route, &existing) < 0)
|
if (route_get(NULL, link, route, &existing) < 0)
|
||||||
link->dhcp6_pd_configured = false;
|
link->dhcp6_pd_configured = false;
|
||||||
@ -359,15 +359,15 @@ static void log_dhcp6_pd_address(Link *link, const Address *address) {
|
|||||||
|
|
||||||
log_link_full(link, log_level, "DHCPv6-PD address %s (valid %s, preferred %s)",
|
log_link_full(link, log_level, "DHCPv6-PD address %s (valid %s, preferred %s)",
|
||||||
strna(buffer),
|
strna(buffer),
|
||||||
FORMAT_LIFETIME(address->cinfo.ifa_valid),
|
FORMAT_LIFETIME(address->lifetime_valid_usec),
|
||||||
FORMAT_LIFETIME(address->cinfo.ifa_prefered));
|
FORMAT_LIFETIME(address->lifetime_preferred_usec));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dhcp6_pd_request_address(
|
static int dhcp6_pd_request_address(
|
||||||
Link *link,
|
Link *link,
|
||||||
const struct in6_addr *prefix,
|
const struct in6_addr *prefix,
|
||||||
uint32_t lifetime_preferred,
|
usec_t lifetime_preferred_usec,
|
||||||
uint32_t lifetime_valid) {
|
usec_t lifetime_valid_usec) {
|
||||||
|
|
||||||
_cleanup_set_free_ Set *addresses = NULL;
|
_cleanup_set_free_ Set *addresses = NULL;
|
||||||
struct in6_addr *a;
|
struct in6_addr *a;
|
||||||
@ -396,8 +396,8 @@ static int dhcp6_pd_request_address(
|
|||||||
address->family = AF_INET6;
|
address->family = AF_INET6;
|
||||||
address->in_addr.in6 = *a;
|
address->in_addr.in6 = *a;
|
||||||
address->prefixlen = 64;
|
address->prefixlen = 64;
|
||||||
address->cinfo.ifa_prefered = lifetime_preferred;
|
address->lifetime_preferred_usec = lifetime_preferred_usec;
|
||||||
address->cinfo.ifa_valid = lifetime_valid;
|
address->lifetime_valid_usec = lifetime_valid_usec;
|
||||||
SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
|
SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
|
||||||
address->route_metric = link->network->dhcp6_pd_route_metric;
|
address->route_metric = link->network->dhcp6_pd_route_metric;
|
||||||
|
|
||||||
@ -420,9 +420,8 @@ static int dhcp6_pd_request_address(
|
|||||||
static int dhcp6_pd_assign_prefix(
|
static int dhcp6_pd_assign_prefix(
|
||||||
Link *link,
|
Link *link,
|
||||||
const struct in6_addr *prefix,
|
const struct in6_addr *prefix,
|
||||||
usec_t timestamp_usec,
|
usec_t lifetime_preferred_usec,
|
||||||
uint32_t lifetime_preferred,
|
usec_t lifetime_valid_usec) {
|
||||||
uint32_t lifetime_valid) {
|
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -431,16 +430,16 @@ static int dhcp6_pd_assign_prefix(
|
|||||||
assert(prefix);
|
assert(prefix);
|
||||||
|
|
||||||
if (link->network->dhcp6_pd_announce) {
|
if (link->network->dhcp6_pd_announce) {
|
||||||
r = radv_add_prefix(link, prefix, 64, lifetime_preferred, lifetime_valid);
|
r = radv_add_prefix(link, prefix, 64, lifetime_preferred_usec, lifetime_valid_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dhcp6_pd_request_route(link, prefix, timestamp_usec, lifetime_valid);
|
r = dhcp6_pd_request_route(link, prefix, lifetime_valid_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = dhcp6_pd_request_address(link, prefix, lifetime_preferred, lifetime_valid);
|
r = dhcp6_pd_request_address(link, prefix, lifetime_preferred_usec, lifetime_valid_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -528,9 +527,8 @@ static int dhcp6_pd_prefix_distribute(
|
|||||||
Link *dhcp6_link,
|
Link *dhcp6_link,
|
||||||
const struct in6_addr *pd_prefix,
|
const struct in6_addr *pd_prefix,
|
||||||
uint8_t pd_prefix_len,
|
uint8_t pd_prefix_len,
|
||||||
usec_t timestamp_usec,
|
usec_t lifetime_preferred_usec,
|
||||||
uint32_t lifetime_preferred,
|
usec_t lifetime_valid_usec,
|
||||||
uint32_t lifetime_valid,
|
|
||||||
bool assign_preferred_subnet_id) {
|
bool assign_preferred_subnet_id) {
|
||||||
|
|
||||||
Link *link;
|
Link *link;
|
||||||
@ -562,7 +560,7 @@ static int dhcp6_pd_prefix_distribute(
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
(void) in6_addr_prefix_to_string(&assigned_prefix, 64, &buf);
|
(void) in6_addr_prefix_to_string(&assigned_prefix, 64, &buf);
|
||||||
r = dhcp6_pd_assign_prefix(link, &assigned_prefix, timestamp_usec, lifetime_preferred, lifetime_valid);
|
r = dhcp6_pd_assign_prefix(link, &assigned_prefix, lifetime_preferred_usec, lifetime_valid_usec);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_link_warning_errno(link, r, "Failed to assign/update prefix %s: %m", strna(buf));
|
log_link_warning_errno(link, r, "Failed to assign/update prefix %s: %m", strna(buf));
|
||||||
if (link == dhcp6_link)
|
if (link == dhcp6_link)
|
||||||
@ -748,7 +746,7 @@ static int dhcp6_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *addr, uint8_t prefixlen, usec_t timestamp_usec, uint32_t lifetime_sec) {
|
static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *addr, uint8_t prefixlen, usec_t lifetime_usec) {
|
||||||
_cleanup_(route_freep) Route *route = NULL;
|
_cleanup_(route_freep) Route *route = NULL;
|
||||||
_cleanup_free_ char *buf = NULL;
|
_cleanup_free_ char *buf = NULL;
|
||||||
Route *existing;
|
Route *existing;
|
||||||
@ -777,7 +775,7 @@ static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *ad
|
|||||||
route->type = RTN_UNREACHABLE;
|
route->type = RTN_UNREACHABLE;
|
||||||
route->protocol = RTPROT_DHCP;
|
route->protocol = RTPROT_DHCP;
|
||||||
route->priority = DHCP_ROUTE_METRIC;
|
route->priority = DHCP_ROUTE_METRIC;
|
||||||
route->lifetime = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
|
route->lifetime_usec = lifetime_usec;
|
||||||
|
|
||||||
if (route_get(link->manager, NULL, route, &existing) < 0)
|
if (route_get(link->manager, NULL, route, &existing) < 0)
|
||||||
link->dhcp6_configured = false;
|
link->dhcp6_configured = false;
|
||||||
@ -851,22 +849,26 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) {
|
for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) {
|
||||||
uint32_t lifetime_preferred, lifetime_valid;
|
uint32_t lifetime_preferred_sec, lifetime_valid_sec;
|
||||||
|
usec_t lifetime_preferred_usec, lifetime_valid_usec;
|
||||||
struct in6_addr pd_prefix;
|
struct in6_addr pd_prefix;
|
||||||
uint8_t pd_prefix_len;
|
uint8_t pd_prefix_len;
|
||||||
|
|
||||||
r = sd_dhcp6_lease_get_pd(dhcp6_link->dhcp6_lease, &pd_prefix, &pd_prefix_len,
|
r = sd_dhcp6_lease_get_pd(dhcp6_link->dhcp6_lease, &pd_prefix, &pd_prefix_len,
|
||||||
&lifetime_preferred, &lifetime_valid);
|
&lifetime_preferred_sec, &lifetime_valid_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
|
||||||
|
lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
|
||||||
|
|
||||||
r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len);
|
r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, timestamp_usec, lifetime_valid);
|
r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len, lifetime_valid_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -898,9 +900,8 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
|
|||||||
r = dhcp6_pd_prefix_distribute(dhcp6_link,
|
r = dhcp6_pd_prefix_distribute(dhcp6_link,
|
||||||
&pd_prefix,
|
&pd_prefix,
|
||||||
pd_prefix_len,
|
pd_prefix_len,
|
||||||
timestamp_usec,
|
lifetime_preferred_usec,
|
||||||
lifetime_preferred,
|
lifetime_valid_usec,
|
||||||
lifetime_valid,
|
|
||||||
true);
|
true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -908,9 +909,8 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
|
|||||||
r = dhcp6_pd_prefix_distribute(dhcp6_link,
|
r = dhcp6_pd_prefix_distribute(dhcp6_link,
|
||||||
&pd_prefix,
|
&pd_prefix,
|
||||||
pd_prefix_len,
|
pd_prefix_len,
|
||||||
timestamp_usec,
|
lifetime_preferred_usec,
|
||||||
lifetime_preferred,
|
lifetime_valid_usec,
|
||||||
lifetime_valid,
|
|
||||||
false);
|
false);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -975,8 +975,8 @@ static void log_dhcp6_address(Link *link, const Address *address) {
|
|||||||
|
|
||||||
log_link_warning(link, "DHCPv6 address %s/%u (valid %s, preferred %s) conflicts the address %s/%u%s.",
|
log_link_warning(link, "DHCPv6 address %s/%u (valid %s, preferred %s) conflicts the address %s/%u%s.",
|
||||||
strna(buffer), address->prefixlen,
|
strna(buffer), address->prefixlen,
|
||||||
FORMAT_LIFETIME(address->cinfo.ifa_valid),
|
FORMAT_LIFETIME(address->lifetime_valid_usec),
|
||||||
FORMAT_LIFETIME(address->cinfo.ifa_prefered),
|
FORMAT_LIFETIME(address->lifetime_preferred_usec),
|
||||||
strna(buffer), existing->prefixlen,
|
strna(buffer), existing->prefixlen,
|
||||||
by_ndisc ? " assigned by NDisc. Please try to use or update IPv6Token= setting "
|
by_ndisc ? " assigned by NDisc. Please try to use or update IPv6Token= setting "
|
||||||
"to change the address generated by NDISC, or disable UseAutonomousPrefix=" : "");
|
"to change the address generated by NDISC, or disable UseAutonomousPrefix=" : "");
|
||||||
@ -985,15 +985,15 @@ static void log_dhcp6_address(Link *link, const Address *address) {
|
|||||||
simple_log:
|
simple_log:
|
||||||
log_link_full(link, log_level, "DHCPv6 address %s/%u (valid %s, preferred %s)",
|
log_link_full(link, log_level, "DHCPv6 address %s/%u (valid %s, preferred %s)",
|
||||||
strna(buffer), address->prefixlen,
|
strna(buffer), address->prefixlen,
|
||||||
FORMAT_LIFETIME(address->cinfo.ifa_valid),
|
FORMAT_LIFETIME(address->lifetime_valid_usec),
|
||||||
FORMAT_LIFETIME(address->cinfo.ifa_prefered));
|
FORMAT_LIFETIME(address->lifetime_preferred_usec));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dhcp6_request_address(
|
static int dhcp6_request_address(
|
||||||
Link *link,
|
Link *link,
|
||||||
const struct in6_addr *ip6_addr,
|
const struct in6_addr *ip6_addr,
|
||||||
uint32_t lifetime_preferred,
|
usec_t lifetime_preferred_usec,
|
||||||
uint32_t lifetime_valid) {
|
usec_t lifetime_valid_usec) {
|
||||||
|
|
||||||
_cleanup_(address_freep) Address *addr = NULL;
|
_cleanup_(address_freep) Address *addr = NULL;
|
||||||
Address *existing;
|
Address *existing;
|
||||||
@ -1008,8 +1008,8 @@ static int dhcp6_request_address(
|
|||||||
addr->in_addr.in6 = *ip6_addr;
|
addr->in_addr.in6 = *ip6_addr;
|
||||||
addr->flags = IFA_F_NOPREFIXROUTE;
|
addr->flags = IFA_F_NOPREFIXROUTE;
|
||||||
addr->prefixlen = 128;
|
addr->prefixlen = 128;
|
||||||
addr->cinfo.ifa_prefered = lifetime_preferred;
|
addr->lifetime_preferred_usec = lifetime_preferred_usec;
|
||||||
addr->cinfo.ifa_valid = lifetime_valid;
|
addr->lifetime_valid_usec = lifetime_valid_usec;
|
||||||
|
|
||||||
log_dhcp6_address(link, addr);
|
log_dhcp6_address(link, addr);
|
||||||
|
|
||||||
@ -1031,6 +1031,7 @@ static int dhcp6_request_address(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int dhcp6_address_acquired(Link *link) {
|
static int dhcp6_address_acquired(Link *link) {
|
||||||
|
usec_t timestamp_usec;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
@ -1040,15 +1041,21 @@ static int dhcp6_address_acquired(Link *link) {
|
|||||||
if (!link->network->dhcp6_use_address)
|
if (!link->network->dhcp6_use_address)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
r = sd_dhcp6_lease_get_timestamp(link->dhcp6_lease, clock_boottime_or_monotonic(), ×tamp_usec);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_warning_errno(link, r, "Failed to get timestamp of DHCPv6 lease: %m");
|
||||||
|
|
||||||
for (sd_dhcp6_lease_reset_address_iter(link->dhcp6_lease);;) {
|
for (sd_dhcp6_lease_reset_address_iter(link->dhcp6_lease);;) {
|
||||||
uint32_t lifetime_preferred, lifetime_valid;
|
uint32_t lifetime_preferred_sec, lifetime_valid_sec;
|
||||||
struct in6_addr ip6_addr;
|
struct in6_addr ip6_addr;
|
||||||
|
|
||||||
r = sd_dhcp6_lease_get_address(link->dhcp6_lease, &ip6_addr, &lifetime_preferred, &lifetime_valid);
|
r = sd_dhcp6_lease_get_address(link->dhcp6_lease, &ip6_addr, &lifetime_preferred_sec, &lifetime_valid_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
r = dhcp6_request_address(link, &ip6_addr, lifetime_preferred, lifetime_valid);
|
r = dhcp6_request_address(link, &ip6_addr,
|
||||||
|
usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec),
|
||||||
|
usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -291,23 +291,29 @@ static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {
|
|||||||
|
|
||||||
static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
||||||
_cleanup_(route_freep) Route *route = NULL;
|
_cleanup_(route_freep) Route *route = NULL;
|
||||||
|
usec_t lifetime_usec, timestamp_usec;
|
||||||
struct in6_addr gateway;
|
struct in6_addr gateway;
|
||||||
uint32_t mtu = 0;
|
uint16_t lifetime_sec;
|
||||||
unsigned preference;
|
unsigned preference;
|
||||||
uint16_t lifetime;
|
uint32_t mtu = 0;
|
||||||
usec_t time_now;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(rt);
|
assert(rt);
|
||||||
|
|
||||||
r = sd_ndisc_router_get_lifetime(rt, &lifetime);
|
r = sd_ndisc_router_get_lifetime(rt, &lifetime_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
|
return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
|
||||||
|
|
||||||
if (lifetime == 0) /* not a default router */
|
if (lifetime_sec == 0) /* not a default router */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
||||||
|
|
||||||
|
lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
|
||||||
|
|
||||||
r = sd_ndisc_router_get_address(rt, &gateway);
|
r = sd_ndisc_router_get_address(rt, &gateway);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
|
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
|
||||||
@ -327,10 +333,6 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
|
return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
|
||||||
|
|
||||||
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
|
||||||
|
|
||||||
if (link->network->ipv6_accept_ra_use_mtu) {
|
if (link->network->ipv6_accept_ra_use_mtu) {
|
||||||
r = sd_ndisc_router_get_mtu(rt, &mtu);
|
r = sd_ndisc_router_get_mtu(rt, &mtu);
|
||||||
if (r < 0 && r != -ENODATA)
|
if (r < 0 && r != -ENODATA)
|
||||||
@ -345,7 +347,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
|||||||
route->pref = preference;
|
route->pref = preference;
|
||||||
route->gw_family = AF_INET6;
|
route->gw_family = AF_INET6;
|
||||||
route->gw.in6 = gateway;
|
route->gw.in6 = gateway;
|
||||||
route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
|
route->lifetime_usec = lifetime_usec;
|
||||||
route->mtu = mtu;
|
route->mtu = mtu;
|
||||||
|
|
||||||
r = ndisc_request_route(TAKE_PTR(route), link, rt);
|
r = ndisc_request_route(TAKE_PTR(route), link, rt);
|
||||||
@ -367,7 +369,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
|||||||
route->gw.in6 = gateway;
|
route->gw.in6 = gateway;
|
||||||
if (!route->pref_set)
|
if (!route->pref_set)
|
||||||
route->pref = preference;
|
route->pref = preference;
|
||||||
route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
|
route->lifetime_usec = lifetime_usec;
|
||||||
if (route->mtu == 0)
|
if (route->mtu == 0)
|
||||||
route->mtu = mtu;
|
route->mtu = mtu;
|
||||||
|
|
||||||
@ -380,19 +382,17 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
|
static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
|
||||||
uint32_t lifetime_valid, lifetime_preferred;
|
uint32_t lifetime_valid_sec, lifetime_preferred_sec;
|
||||||
|
usec_t lifetime_valid_usec, lifetime_preferred_usec, timestamp_usec;
|
||||||
_cleanup_set_free_ Set *addresses = NULL;
|
_cleanup_set_free_ Set *addresses = NULL;
|
||||||
struct in6_addr prefix, *a;
|
struct in6_addr prefix, *a;
|
||||||
unsigned prefixlen;
|
unsigned prefixlen;
|
||||||
usec_t time_now;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(rt);
|
assert(rt);
|
||||||
|
|
||||||
/* Do not use clock_boottime_or_monotonic() here, as the kernel internally manages cstamp and
|
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
|
||||||
* tstamp with jiffies, and it is not increased while the system is suspended. */
|
|
||||||
r = sd_ndisc_router_get_timestamp(rt, CLOCK_MONOTONIC, &time_now);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
||||||
|
|
||||||
@ -413,23 +413,26 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid);
|
r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
|
return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
|
||||||
|
|
||||||
if (lifetime_valid == 0) {
|
if (lifetime_valid_sec == 0) {
|
||||||
log_link_debug(link, "Ignoring prefix as its valid lifetime is zero.");
|
log_link_debug(link, "Ignoring prefix as its valid lifetime is zero.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred);
|
r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
|
return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
|
||||||
|
|
||||||
/* The preferred lifetime is never greater than the valid lifetime */
|
/* The preferred lifetime is never greater than the valid lifetime */
|
||||||
if (lifetime_preferred > lifetime_valid)
|
if (lifetime_preferred_sec > lifetime_valid_sec)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
|
||||||
|
lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
|
||||||
|
|
||||||
r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses);
|
r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to generate SLAAC addresses: %m");
|
return log_link_error_errno(link, r, "Failed to generate SLAAC addresses: %m");
|
||||||
@ -446,8 +449,8 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
|
|||||||
address->in_addr.in6 = *a;
|
address->in_addr.in6 = *a;
|
||||||
address->prefixlen = prefixlen;
|
address->prefixlen = prefixlen;
|
||||||
address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
|
address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
|
||||||
address->cinfo.ifa_valid = lifetime_valid;
|
address->lifetime_valid_usec = lifetime_valid_usec;
|
||||||
address->cinfo.ifa_prefered = lifetime_preferred;
|
address->lifetime_preferred_usec = lifetime_preferred_usec;
|
||||||
|
|
||||||
/* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by
|
/* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by
|
||||||
* honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events.
|
* honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events.
|
||||||
@ -456,9 +459,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
|
|||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
/* If the address is already assigned, but not valid anymore, then refuse to
|
/* If the address is already assigned, but not valid anymore, then refuse to
|
||||||
* update the address, and it will be removed. */
|
* update the address, and it will be removed. */
|
||||||
if (e->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME &&
|
if (e->lifetime_valid_usec < timestamp_usec)
|
||||||
usec_add(e->cinfo.tstamp / 100 * USEC_PER_SEC,
|
|
||||||
e->cinfo.ifa_valid * USEC_PER_SEC) < time_now)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,15 +473,22 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
|
|||||||
|
|
||||||
static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
||||||
_cleanup_(route_freep) Route *route = NULL;
|
_cleanup_(route_freep) Route *route = NULL;
|
||||||
usec_t time_now;
|
usec_t timestamp_usec;
|
||||||
uint32_t lifetime;
|
uint32_t lifetime_sec;
|
||||||
unsigned prefixlen;
|
unsigned prefixlen;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(rt);
|
assert(rt);
|
||||||
|
|
||||||
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
|
r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_sec);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
|
||||||
|
|
||||||
|
if (lifetime_sec == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
||||||
|
|
||||||
@ -488,10 +496,6 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get prefix length: %m");
|
return log_link_error_errno(link, r, "Failed to get prefix length: %m");
|
||||||
|
|
||||||
r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
|
|
||||||
|
|
||||||
r = route_new(&route);
|
r = route_new(&route);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
@ -499,7 +503,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
|||||||
route->family = AF_INET6;
|
route->family = AF_INET6;
|
||||||
route->flags = RTM_F_PREFIX;
|
route->flags = RTM_F_PREFIX;
|
||||||
route->dst_prefixlen = prefixlen;
|
route->dst_prefixlen = prefixlen;
|
||||||
route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
|
route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
|
||||||
|
|
||||||
r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
|
r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -514,19 +518,19 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
|||||||
|
|
||||||
static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
|
static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
|
||||||
_cleanup_(route_freep) Route *route = NULL;
|
_cleanup_(route_freep) Route *route = NULL;
|
||||||
struct in6_addr gateway, dst;
|
|
||||||
uint32_t lifetime;
|
|
||||||
unsigned preference, prefixlen;
|
unsigned preference, prefixlen;
|
||||||
usec_t time_now;
|
struct in6_addr gateway, dst;
|
||||||
|
uint32_t lifetime_sec;
|
||||||
|
usec_t timestamp_usec;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
|
||||||
r = sd_ndisc_router_route_get_lifetime(rt, &lifetime);
|
r = sd_ndisc_router_route_get_lifetime(rt, &lifetime_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m");
|
return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m");
|
||||||
|
|
||||||
if (lifetime == 0)
|
if (lifetime_sec == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = sd_ndisc_router_route_get_address(rt, &dst);
|
r = sd_ndisc_router_route_get_address(rt, &dst);
|
||||||
@ -568,7 +572,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
|
return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
|
||||||
|
|
||||||
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
|
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
||||||
|
|
||||||
@ -582,7 +586,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
|
|||||||
route->gw_family = AF_INET6;
|
route->gw_family = AF_INET6;
|
||||||
route->dst.in6 = dst;
|
route->dst.in6 = dst;
|
||||||
route->dst_prefixlen = prefixlen;
|
route->dst_prefixlen = prefixlen;
|
||||||
route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
|
route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
|
||||||
|
|
||||||
r = ndisc_request_route(TAKE_PTR(route), link, rt);
|
r = ndisc_request_route(TAKE_PTR(route), link, rt);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -607,10 +611,10 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
|||||||
free);
|
free);
|
||||||
|
|
||||||
static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
|
static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
|
||||||
uint32_t lifetime;
|
usec_t lifetime_usec, timestamp_usec;
|
||||||
|
uint32_t lifetime_sec;
|
||||||
const struct in6_addr *a;
|
const struct in6_addr *a;
|
||||||
struct in6_addr router;
|
struct in6_addr router;
|
||||||
usec_t time_now;
|
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
int n, r;
|
int n, r;
|
||||||
|
|
||||||
@ -621,21 +625,23 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
|
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
|
||||||
|
|
||||||
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
|
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
||||||
|
|
||||||
r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime);
|
r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
|
return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
|
||||||
|
|
||||||
|
if (lifetime_sec == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
|
||||||
|
|
||||||
n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
|
n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
|
return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
|
||||||
|
|
||||||
if (lifetime == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (n >= (int) NDISC_RDNSS_MAX) {
|
if (n >= (int) NDISC_RDNSS_MAX) {
|
||||||
log_link_warning(link, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX);
|
log_link_warning(link, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX);
|
||||||
n = NDISC_RDNSS_MAX;
|
n = NDISC_RDNSS_MAX;
|
||||||
@ -651,7 +657,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
|
|||||||
if (rdnss) {
|
if (rdnss) {
|
||||||
rdnss->marked = false;
|
rdnss->marked = false;
|
||||||
rdnss->router = router;
|
rdnss->router = router;
|
||||||
rdnss->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC);
|
rdnss->lifetime_usec = lifetime_usec;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,7 +668,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
|
|||||||
*x = (NDiscRDNSS) {
|
*x = (NDiscRDNSS) {
|
||||||
.address = a[j],
|
.address = a[j],
|
||||||
.router = router,
|
.router = router,
|
||||||
.valid_until = usec_add(time_now, lifetime * USEC_PER_SEC),
|
.lifetime_usec = lifetime_usec,
|
||||||
};
|
};
|
||||||
|
|
||||||
r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
|
r = set_ensure_consume(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops, TAKE_PTR(x));
|
||||||
@ -696,9 +702,9 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
|||||||
|
|
||||||
static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
|
static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
|
||||||
_cleanup_strv_free_ char **l = NULL;
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
|
usec_t lifetime_usec, timestamp_usec;
|
||||||
struct in6_addr router;
|
struct in6_addr router;
|
||||||
uint32_t lifetime;
|
uint32_t lifetime_sec;
|
||||||
usec_t time_now;
|
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
char **j;
|
char **j;
|
||||||
int r;
|
int r;
|
||||||
@ -710,21 +716,23 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
|
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
|
||||||
|
|
||||||
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
|
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
|
||||||
|
|
||||||
r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime);
|
r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
|
return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
|
||||||
|
|
||||||
|
if (lifetime_sec == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
|
||||||
|
|
||||||
r = sd_ndisc_router_dnssl_get_domains(rt, &l);
|
r = sd_ndisc_router_dnssl_get_domains(rt, &l);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
|
return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
|
||||||
|
|
||||||
if (lifetime == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (strv_length(l) >= NDISC_DNSSL_MAX) {
|
if (strv_length(l) >= NDISC_DNSSL_MAX) {
|
||||||
log_link_warning(link, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX);
|
log_link_warning(link, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX);
|
||||||
STRV_FOREACH(j, l + NDISC_DNSSL_MAX)
|
STRV_FOREACH(j, l + NDISC_DNSSL_MAX)
|
||||||
@ -745,12 +753,12 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
|
|||||||
if (dnssl) {
|
if (dnssl) {
|
||||||
dnssl->marked = false;
|
dnssl->marked = false;
|
||||||
dnssl->router = router;
|
dnssl->router = router;
|
||||||
dnssl->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC);
|
dnssl->lifetime_usec = lifetime_usec;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->router = router;
|
s->router = router;
|
||||||
s->valid_until = usec_add(time_now, lifetime * USEC_PER_SEC);
|
s->lifetime_usec = lifetime_usec;
|
||||||
|
|
||||||
r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
|
r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -1042,11 +1050,11 @@ void ndisc_vacuum(Link *link) {
|
|||||||
time_now = now(clock_boottime_or_monotonic());
|
time_now = now(clock_boottime_or_monotonic());
|
||||||
|
|
||||||
SET_FOREACH(r, link->ndisc_rdnss)
|
SET_FOREACH(r, link->ndisc_rdnss)
|
||||||
if (r->valid_until < time_now)
|
if (r->lifetime_usec < time_now)
|
||||||
free(set_remove(link->ndisc_rdnss, r));
|
free(set_remove(link->ndisc_rdnss, r));
|
||||||
|
|
||||||
SET_FOREACH(d, link->ndisc_dnssl)
|
SET_FOREACH(d, link->ndisc_dnssl)
|
||||||
if (d->valid_until < time_now)
|
if (d->lifetime_usec < time_now)
|
||||||
free(set_remove(link->ndisc_dnssl, d));
|
free(set_remove(link->ndisc_dnssl, d));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,9 @@ typedef struct NDiscRDNSS {
|
|||||||
/* Used when GC'ing old DNS servers when configuration changes. */
|
/* Used when GC'ing old DNS servers when configuration changes. */
|
||||||
bool marked;
|
bool marked;
|
||||||
struct in6_addr router;
|
struct in6_addr router;
|
||||||
usec_t valid_until;
|
/* This is an absolute point in time, and NOT a timespan/duration.
|
||||||
|
* Must be specified with clock_boottime_or_monotonic(). */
|
||||||
|
usec_t lifetime_usec;
|
||||||
struct in6_addr address;
|
struct in6_addr address;
|
||||||
} NDiscRDNSS;
|
} NDiscRDNSS;
|
||||||
|
|
||||||
@ -27,7 +29,9 @@ typedef struct NDiscDNSSL {
|
|||||||
/* Used when GC'ing old domains when configuration changes. */
|
/* Used when GC'ing old domains when configuration changes. */
|
||||||
bool marked;
|
bool marked;
|
||||||
struct in6_addr router;
|
struct in6_addr router;
|
||||||
usec_t valid_until;
|
/* This is an absolute point in time, and NOT a timespan/duration.
|
||||||
|
* Must be specified with clock_boottime_or_monotonic(). */
|
||||||
|
usec_t lifetime_usec;
|
||||||
/* The domain name follows immediately. */
|
/* The domain name follows immediately. */
|
||||||
} NDiscDNSSL;
|
} NDiscDNSSL;
|
||||||
|
|
||||||
|
@ -629,10 +629,11 @@ int radv_add_prefix(
|
|||||||
Link *link,
|
Link *link,
|
||||||
const struct in6_addr *prefix,
|
const struct in6_addr *prefix,
|
||||||
uint8_t prefix_len,
|
uint8_t prefix_len,
|
||||||
uint32_t lifetime_preferred,
|
usec_t lifetime_preferred_usec,
|
||||||
uint32_t lifetime_valid) {
|
usec_t lifetime_valid_usec) {
|
||||||
|
|
||||||
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
|
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
|
||||||
|
usec_t now_usec;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
@ -640,6 +641,8 @@ int radv_add_prefix(
|
|||||||
if (!link->radv)
|
if (!link->radv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
now_usec = now(clock_boottime_or_monotonic());
|
||||||
|
|
||||||
r = sd_radv_prefix_new(&p);
|
r = sd_radv_prefix_new(&p);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -648,11 +651,11 @@ int radv_add_prefix(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_radv_prefix_set_preferred_lifetime(p, lifetime_preferred);
|
r = sd_radv_prefix_set_preferred_lifetime(p, usec_sub_unsigned(lifetime_preferred_usec, now_usec) / USEC_PER_SEC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_radv_prefix_set_valid_lifetime(p, lifetime_valid);
|
r = sd_radv_prefix_set_valid_lifetime(p, usec_sub_unsigned(lifetime_valid_usec, now_usec) / USEC_PER_SEC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ int link_request_radv_addresses(Link *link);
|
|||||||
|
|
||||||
int radv_update_mac(Link *link);
|
int radv_update_mac(Link *link);
|
||||||
int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len,
|
int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len,
|
||||||
uint32_t lifetime_preferred, uint32_t lifetime_valid);
|
usec_t lifetime_preferred_usec, usec_t lifetime_valid_usec);
|
||||||
|
|
||||||
int request_process_radv(Request *req);
|
int request_process_radv(Request *req);
|
||||||
int link_request_radv(Link *link);
|
int link_request_radv(Link *link);
|
||||||
|
@ -186,7 +186,7 @@ int route_new(Route **ret) {
|
|||||||
.protocol = RTPROT_UNSPEC,
|
.protocol = RTPROT_UNSPEC,
|
||||||
.type = RTN_UNICAST,
|
.type = RTN_UNICAST,
|
||||||
.table = RT_TABLE_MAIN,
|
.table = RT_TABLE_MAIN,
|
||||||
.lifetime = USEC_INFINITY,
|
.lifetime_usec = USEC_INFINITY,
|
||||||
.quickack = -1,
|
.quickack = -1,
|
||||||
.fast_open_no_cookie = -1,
|
.fast_open_no_cookie = -1,
|
||||||
.gateway_onlink = -1,
|
.gateway_onlink = -1,
|
||||||
@ -1240,7 +1240,7 @@ static int route_setup_timer(Route *route, const struct rta_cacheinfo *cacheinfo
|
|||||||
|
|
||||||
manager = route->manager ?: route->link->manager;
|
manager = route->manager ?: route->link->manager;
|
||||||
|
|
||||||
if (route->lifetime == USEC_INFINITY)
|
if (route->lifetime_usec == USEC_INFINITY)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (cacheinfo && cacheinfo->rta_expires != 0)
|
if (cacheinfo && cacheinfo->rta_expires != 0)
|
||||||
@ -1248,7 +1248,7 @@ static int route_setup_timer(Route *route, const struct rta_cacheinfo *cacheinfo
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = event_reset_time(manager->event, &route->expire, clock_boottime_or_monotonic(),
|
r = event_reset_time(manager->event, &route->expire, clock_boottime_or_monotonic(),
|
||||||
route->lifetime, 0, route_expire_handler, route, 0, "route-expiration", true);
|
route->lifetime_usec, 0, route_expire_handler, route, 0, "route-expiration", true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1392,9 +1392,9 @@ static int route_configure(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (route->lifetime != USEC_INFINITY) {
|
if (route->lifetime_usec != USEC_INFINITY) {
|
||||||
r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
|
r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
|
||||||
MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX));
|
MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
|
return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
|
||||||
}
|
}
|
||||||
@ -3039,7 +3039,7 @@ static int route_section_verify(Route *route, Network *network) {
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Currently, we do not support static route with finite lifetime. */
|
/* Currently, we do not support static route with finite lifetime. */
|
||||||
assert(route->lifetime == USEC_INFINITY);
|
assert(route->lifetime_usec == USEC_INFINITY);
|
||||||
|
|
||||||
if (route->gateway_from_dhcp_or_ra) {
|
if (route->gateway_from_dhcp_or_ra) {
|
||||||
if (route->gw_family == AF_UNSPEC) {
|
if (route->gw_family == AF_UNSPEC) {
|
||||||
|
@ -61,7 +61,10 @@ typedef struct Route {
|
|||||||
union in_addr_union prefsrc;
|
union in_addr_union prefsrc;
|
||||||
OrderedSet *multipath_routes;
|
OrderedSet *multipath_routes;
|
||||||
|
|
||||||
usec_t lifetime;
|
/* This is an absolute point in time, and NOT a timespan/duration.
|
||||||
|
* Must be specified with clock_boottime_or_monotonic(). */
|
||||||
|
usec_t lifetime_usec;
|
||||||
|
/* Used when kernel does not support RTA_EXPIRES attribute. */
|
||||||
sd_event_source *expire;
|
sd_event_source *expire;
|
||||||
} Route;
|
} Route;
|
||||||
|
|
||||||
|
@ -2,21 +2,26 @@
|
|||||||
|
|
||||||
#include "networkd-address.h"
|
#include "networkd-address.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
#include "time-util.h"
|
||||||
|
|
||||||
static void test_FORMAT_LIFETIME_one(uint32_t lifetime, const char *expected) {
|
static void test_FORMAT_LIFETIME_one(usec_t lifetime, const char *expected) {
|
||||||
const char *t = FORMAT_LIFETIME(lifetime);
|
const char *t = FORMAT_LIFETIME(lifetime);
|
||||||
|
|
||||||
log_debug("%"PRIu32 " → \"%s\" (expected \"%s\")", lifetime, t, expected);
|
log_debug(USEC_FMT " → \"%s\" (expected \"%s\")", lifetime, t, expected);
|
||||||
assert_se(streq(t, expected));
|
assert_se(streq(t, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_FORMAT_LIFETIME(void) {
|
static void test_FORMAT_LIFETIME(void) {
|
||||||
|
usec_t now_usec;
|
||||||
|
|
||||||
log_info("/* %s */", __func__);
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
test_FORMAT_LIFETIME_one(0, "for 0");
|
now_usec = now(CLOCK_MONOTONIC);
|
||||||
test_FORMAT_LIFETIME_one(1, "for 1s");
|
|
||||||
test_FORMAT_LIFETIME_one(3 * (USEC_PER_WEEK/USEC_PER_SEC), "for 3w");
|
test_FORMAT_LIFETIME_one(now_usec, "for 0");
|
||||||
test_FORMAT_LIFETIME_one(CACHE_INFO_INFINITY_LIFE_TIME, "forever");
|
test_FORMAT_LIFETIME_one(usec_add(now_usec, 2 * USEC_PER_SEC - 1), "for 1s");
|
||||||
|
test_FORMAT_LIFETIME_one(usec_add(now_usec, 3 * USEC_PER_WEEK + USEC_PER_SEC - 1), "for 3w");
|
||||||
|
test_FORMAT_LIFETIME_one(USEC_INFINITY, "forever");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user