From def4741bd74b947cfbbc1929abd81b68acbeadd0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 14 Jul 2022 02:53:03 +0900 Subject: [PATCH 1/3] network: use sd_event_now() --- src/network/networkd-address.c | 18 ++++++++++-------- src/network/networkd-dhcp-prefix-delegation.c | 12 ++++++++---- src/network/networkd-dhcp4.c | 5 ++++- src/network/networkd-ndisc.c | 9 +++++---- src/network/networkd-route.c | 5 ++++- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 8e8d5f7781..7131b0e04c 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -212,13 +212,14 @@ void address_set_broadcast(Address *a, Link *link) { a->broadcast.s_addr = a->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> a->prefixlen); } -static struct ifa_cacheinfo *address_set_cinfo(const Address *a, struct ifa_cacheinfo *cinfo) { +static struct ifa_cacheinfo *address_set_cinfo(Manager *m, const Address *a, struct ifa_cacheinfo *cinfo) { usec_t now_usec; + assert(m); assert(a); assert(cinfo); - now_usec = now(CLOCK_BOOTTIME); + assert_se(sd_event_now(m->event, CLOCK_BOOTTIME, &now_usec) >= 0); *cinfo = (struct ifa_cacheinfo) { .ifa_valid = MIN(usec_sub_unsigned(a->lifetime_valid_usec, now_usec) / USEC_PER_SEC, UINT32_MAX), @@ -228,13 +229,14 @@ static struct ifa_cacheinfo *address_set_cinfo(const Address *a, struct ifa_cach return cinfo; } -static void address_set_lifetime(Address *a, const struct ifa_cacheinfo *cinfo) { +static void address_set_lifetime(Manager *m, Address *a, const struct ifa_cacheinfo *cinfo) { usec_t now_usec; + assert(m); assert(a); assert(cinfo); - now_usec = now(CLOCK_BOOTTIME); + assert_se(sd_event_now(m->event, CLOCK_BOOTTIME, &now_usec) >= 0); if (cinfo->ifa_valid == UINT32_MAX) a->lifetime_valid_usec = USEC_INFINITY; @@ -1078,7 +1080,7 @@ static int address_configure(const Address *address, Link *link, Request *req) { } r = sd_netlink_message_append_cache_info(m, IFA_CACHEINFO, - address_set_cinfo(address, &(struct ifa_cacheinfo) {})); + address_set_cinfo(link->manager, address, &(struct ifa_cacheinfo) {})); if (r < 0) return r; @@ -1455,18 +1457,18 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, /* update flags and etc. */ address->flags = tmp->flags; address->scope = tmp->scope; - address_set_lifetime(address, &cinfo); + address_set_lifetime(m, address, &cinfo); address_enter_configured(address); log_address_debug(address, "Received updated", link); } else { - address_set_lifetime(tmp, &cinfo); + address_set_lifetime(m, tmp, &cinfo); address_enter_configured(tmp); log_address_debug(tmp, "Received new", link); r = address_add(link, tmp); if (r < 0) { log_link_warning_errno(link, r, "Failed to remember foreign address %s, ignoring: %m", - IN_ADDR_PREFIX_TO_STRING(tmp->family, &tmp->in_addr, tmp->prefixlen)); + IN_ADDR_PREFIX_TO_STRING(tmp->family, &tmp->in_addr, tmp->prefixlen)); return 0; } diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 5c923c258c..89ff59abe0 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -854,11 +854,12 @@ static int dhcp4_pd_assign_subnet_prefix(Link *link, Link *uplink) { const struct in_addr *br_addresses; struct in_addr ipv4address; uint32_t lifetime_sec; - usec_t lifetime_usec; + usec_t lifetime_usec, now_usec; int r; assert(link); assert(uplink); + assert(uplink->manager); assert(uplink->dhcp_lease); r = sd_dhcp_lease_get_address(uplink->dhcp_lease, &ipv4address); @@ -869,7 +870,8 @@ static int dhcp4_pd_assign_subnet_prefix(Link *link, Link *uplink) { if (r < 0) return log_link_warning_errno(uplink, r, "Failed to get lifetime of DHCPv4 lease: %m"); - lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now(CLOCK_BOOTTIME)); + assert_se(sd_event_now(uplink->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); + lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec); r = sd_dhcp_lease_get_6rd(uplink->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, &br_addresses, NULL); if (r < 0) @@ -926,11 +928,12 @@ int dhcp4_pd_prefix_acquired(Link *uplink) { union in_addr_union server_address; const struct in_addr *br_addresses; uint32_t lifetime_sec; - usec_t lifetime_usec; + usec_t lifetime_usec, now_usec; Link *link; int r; assert(uplink); + assert(uplink->manager); assert(uplink->dhcp_lease); r = sd_dhcp_lease_get_address(uplink->dhcp_lease, &ipv4address); @@ -941,7 +944,8 @@ int dhcp4_pd_prefix_acquired(Link *uplink) { if (r < 0) return log_link_warning_errno(uplink, r, "Failed to get lifetime of DHCPv4 lease: %m"); - lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now(CLOCK_BOOTTIME)); + assert_se(sd_event_now(uplink->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); + lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec); r = sd_dhcp_lease_get_server_identifier(uplink->dhcp_lease, &server_address.in); if (r < 0) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 5770b48767..86d167e628 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -797,6 +797,7 @@ static int dhcp4_request_address(Link *link, bool announce) { int r; assert(link); + assert(link->manager); assert(link->network); assert(link->dhcp_lease); @@ -814,12 +815,14 @@ static int dhcp4_request_address(Link *link, bool announce) { if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) { uint32_t lifetime_sec; + usec_t now_usec; r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime_sec); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); - lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now(CLOCK_BOOTTIME)); + assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); + lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec); } else lifetime_usec = USEC_INFINITY; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index f66745a4ff..b76b9608f3 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1145,20 +1145,21 @@ int link_request_ndisc(Link *link) { void ndisc_vacuum(Link *link) { NDiscRDNSS *r; NDiscDNSSL *d; - usec_t time_now; + usec_t now_usec; assert(link); + assert(link->manager); /* Removes all RDNSS and DNSSL entries whose validity time has passed */ - time_now = now(CLOCK_BOOTTIME); + assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); SET_FOREACH(r, link->ndisc_rdnss) - if (r->lifetime_usec < time_now) + if (r->lifetime_usec < now_usec) free(set_remove(link->ndisc_rdnss, r)); SET_FOREACH(d, link->ndisc_dnssl) - if (d->lifetime_usec < time_now) + if (d->lifetime_usec < now_usec) free(set_remove(link->ndisc_dnssl, d)); } diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 2708f9d79d..adc4660cfd 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1180,8 +1180,11 @@ static int route_configure(const Route *route, Link *link, Request *req) { return r; if (route->lifetime_usec != USEC_INFINITY) { + usec_t now_usec; + + assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); r = sd_netlink_message_append_u32(m, RTA_EXPIRES, - MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now(CLOCK_BOOTTIME)), USEC_PER_SEC), UINT32_MAX)); + MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now_usec), USEC_PER_SEC), UINT32_MAX)); if (r < 0) return r; } From 5235d739605f0f3f91abef9d5e7d8764ae57430c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 14 Jul 2022 02:52:48 +0900 Subject: [PATCH 2/3] network: fix infinite lifetime handling --- src/network/networkd-address.c | 15 ++++----------- src/network/networkd-dhcp-prefix-delegation.c | 18 +++++++----------- src/network/networkd-dhcp4.c | 2 +- src/network/networkd-dhcp6.c | 4 ++-- src/network/networkd-ndisc.c | 14 +++++++------- src/network/networkd-route.c | 11 +++++++---- src/network/networkd-util.h | 12 ++++++++++++ 7 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 7131b0e04c..ba936d932a 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -222,8 +222,8 @@ static struct ifa_cacheinfo *address_set_cinfo(Manager *m, const Address *a, str assert_se(sd_event_now(m->event, CLOCK_BOOTTIME, &now_usec) >= 0); *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), + .ifa_valid = usec_to_sec(a->lifetime_valid_usec, now_usec), + .ifa_prefered = usec_to_sec(a->lifetime_preferred_usec, now_usec), }; return cinfo; @@ -238,15 +238,8 @@ static void address_set_lifetime(Manager *m, Address *a, const struct ifa_cachei assert_se(sd_event_now(m->event, CLOCK_BOOTTIME, &now_usec) >= 0); - 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); + a->lifetime_valid_usec = sec_to_usec(cinfo->ifa_valid, now_usec); + a->lifetime_preferred_usec = sec_to_usec(cinfo->ifa_prefered, now_usec); } static uint32_t address_prefix(const Address *a) { diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 89ff59abe0..62f0192bcb 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -871,7 +871,7 @@ static int dhcp4_pd_assign_subnet_prefix(Link *link, Link *uplink) { return log_link_warning_errno(uplink, r, "Failed to get lifetime of DHCPv4 lease: %m"); assert_se(sd_event_now(uplink->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); - lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec); + lifetime_usec = sec_to_usec(lifetime_sec, now_usec); r = sd_dhcp_lease_get_6rd(uplink->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, &br_addresses, NULL); if (r < 0) @@ -945,7 +945,7 @@ int dhcp4_pd_prefix_acquired(Link *uplink) { return log_link_warning_errno(uplink, r, "Failed to get lifetime of DHCPv4 lease: %m"); assert_se(sd_event_now(uplink->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); - lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec); + lifetime_usec = sec_to_usec(lifetime_sec, now_usec); r = sd_dhcp_lease_get_server_identifier(uplink->dhcp_lease, &server_address.in); if (r < 0) @@ -1036,7 +1036,6 @@ static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) { for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) { uint32_t lifetime_preferred_sec, lifetime_valid_sec; - usec_t lifetime_preferred_usec, lifetime_valid_usec; struct in6_addr pd_prefix; uint8_t pd_prefix_len; @@ -1053,11 +1052,9 @@ static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) { if (r < 0) return r; - 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 = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefix_len, - lifetime_preferred_usec, lifetime_valid_usec, + sec_to_usec(lifetime_preferred_sec, timestamp_usec), + sec_to_usec(lifetime_valid_sec, timestamp_usec), /* is_uplink = */ link == uplink); if (r < 0) return r; @@ -1086,7 +1083,6 @@ int dhcp6_pd_prefix_acquired(Link *uplink) { /* First, logs acquired prefixes and request unreachable routes. */ for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) { uint32_t lifetime_preferred_sec, lifetime_valid_sec; - usec_t lifetime_valid_usec; struct in6_addr pd_prefix; uint8_t pd_prefix_len; @@ -1100,13 +1096,13 @@ int dhcp6_pd_prefix_acquired(Link *uplink) { if (r < 0) return log_link_error_errno(uplink, r, "Failed to mask DHCPv6 delegated prefix: %m"); - lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); - r = dhcp_pd_prefix_add(uplink, &pd_prefix, pd_prefix_len); if (r < 0) return r; - r = dhcp6_request_unreachable_route(uplink, &pd_prefix, pd_prefix_len, lifetime_valid_usec, &server_address); + r = dhcp6_request_unreachable_route(uplink, &pd_prefix, pd_prefix_len, + sec_to_usec(lifetime_valid_sec, timestamp_usec), + &server_address); if (r < 0) return r; } diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 86d167e628..f1412ad352 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -822,7 +822,7 @@ static int dhcp4_request_address(Link *link, bool announce) { return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); - lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec); + lifetime_usec = sec_to_usec(lifetime_sec, now_usec); } else lifetime_usec = USEC_INFINITY; diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 3dc34f0e52..be7bdd6a43 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -266,8 +266,8 @@ static int dhcp6_address_acquired(Link *link) { break; r = dhcp6_request_address(link, &server_address, &ip6_addr, - usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec), - usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec)); + sec_to_usec(lifetime_preferred_sec, timestamp_usec), + sec_to_usec(lifetime_valid_sec, timestamp_usec)); if (r < 0) return r; } diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index b76b9608f3..ed33f0817f 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -320,7 +320,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { 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); + lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec); r = sd_ndisc_router_get_address(rt, &gateway); if (r < 0) @@ -442,8 +442,8 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r if (lifetime_preferred_sec > lifetime_valid_sec) 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); + lifetime_valid_usec = sec_to_usec(lifetime_valid_sec, timestamp_usec); + lifetime_preferred_usec = sec_to_usec(lifetime_preferred_sec, timestamp_usec); r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses); if (r < 0) @@ -519,7 +519,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { route->family = AF_INET6; route->flags = RTM_F_PREFIX; route->dst_prefixlen = prefixlen; - route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec); r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6); if (r < 0) @@ -652,7 +652,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { route->gw_family = AF_INET6; route->dst.in6 = dst; route->dst_prefixlen = prefixlen; - route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec); r = ndisc_request_route(TAKE_PTR(route), link, rt); if (r < 0) @@ -706,7 +706,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { if (lifetime_sec == 0) return 0; - lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec); n = sd_ndisc_router_rdnss_get_addresses(rt, &a); if (n < 0) @@ -800,7 +800,7 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { if (lifetime_sec == 0) return 0; - lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC); + lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec); r = sd_ndisc_router_dnssl_get_domains(rt, &l); if (r < 0) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index adc4660cfd..8ab5aaf0db 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1181,12 +1181,15 @@ static int route_configure(const Route *route, Link *link, Request *req) { if (route->lifetime_usec != USEC_INFINITY) { usec_t now_usec; + uint32_t sec; assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); - r = sd_netlink_message_append_u32(m, RTA_EXPIRES, - MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now_usec), USEC_PER_SEC), UINT32_MAX)); - if (r < 0) - return r; + sec = usec_to_sec(route->lifetime_usec, now_usec); + if (sec != UINT32_MAX) { + r = sd_netlink_message_append_u32(m, RTA_EXPIRES, sec); + if (r < 0) + return r; + } } if (route->ttl_propagate >= 0) { diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h index 0a627588aa..373184a3ed 100644 --- a/src/network/networkd-util.h +++ b/src/network/networkd-util.h @@ -37,6 +37,18 @@ typedef enum NetworkConfigState { NETWORK_CONFIG_STATE_REMOVING = 1 << 5, /* e.g. address_remove() is called, but no response is received yet */ } NetworkConfigState; +static inline usec_t sec16_to_usec(uint16_t sec, usec_t timestamp_usec) { + return sec == UINT16_MAX ? USEC_INFINITY : usec_add(timestamp_usec, sec * USEC_PER_SEC); +} + +static inline usec_t sec_to_usec(uint32_t sec, usec_t timestamp_usec) { + return sec == UINT32_MAX ? USEC_INFINITY : usec_add(timestamp_usec, sec * USEC_PER_SEC); +} + +static inline uint32_t usec_to_sec(usec_t usec, usec_t now_usec) { + return MIN(DIV_ROUND_UP(usec_sub_unsigned(usec, now_usec), USEC_PER_SEC), UINT32_MAX); +} + CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family); CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel); CONFIG_PARSER_PROTOTYPE(config_parse_ip_masquerade); From b9e4ec500eb2f3c6bc65f838d2630771f65fa80b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 14 Jul 2022 02:39:56 +0900 Subject: [PATCH 3/3] network: refuse to configure address or route with 0 valid lifetime Fixes #23625. --- src/network/networkd-address.c | 22 +++++++++++++------- src/network/networkd-route.c | 38 ++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index ba936d932a..a60cd746a4 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -212,7 +212,7 @@ void address_set_broadcast(Address *a, Link *link) { a->broadcast.s_addr = a->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> a->prefixlen); } -static struct ifa_cacheinfo *address_set_cinfo(Manager *m, const Address *a, struct ifa_cacheinfo *cinfo) { +static void address_set_cinfo(Manager *m, const Address *a, struct ifa_cacheinfo *cinfo) { usec_t now_usec; assert(m); @@ -225,8 +225,6 @@ static struct ifa_cacheinfo *address_set_cinfo(Manager *m, const Address *a, str .ifa_valid = usec_to_sec(a->lifetime_valid_usec, now_usec), .ifa_prefered = usec_to_sec(a->lifetime_preferred_usec, now_usec), }; - - return cinfo; } static void address_set_lifetime(Manager *m, Address *a, const struct ifa_cacheinfo *cinfo) { @@ -1030,12 +1028,13 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, return 1; } -static int address_configure(const Address *address, Link *link, Request *req) { +static int address_configure(const Address *address, const struct ifa_cacheinfo *c, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(address); assert(IN_SET(address->family, AF_INET, AF_INET6)); + assert(c); assert(link); assert(link->ifindex > 0); assert(link->manager); @@ -1072,8 +1071,7 @@ static int address_configure(const Address *address, Link *link, Request *req) { return r; } - r = sd_netlink_message_append_cache_info(m, IFA_CACHEINFO, - address_set_cinfo(link->manager, address, &(struct ifa_cacheinfo) {})); + r = sd_netlink_message_append_cache_info(m, IFA_CACHEINFO, c); if (r < 0) return r; @@ -1102,6 +1100,7 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) { } static int address_process_request(Request *req, Link *link, Address *address) { + struct ifa_cacheinfo c; int r; assert(req); @@ -1111,7 +1110,16 @@ static int address_process_request(Request *req, Link *link, Address *address) { if (!address_is_ready_to_configure(link, address)) return 0; - r = address_configure(address, link, req); + address_set_cinfo(link->manager, address, &c); + if (c.ifa_valid == 0) { + log_link_debug(link, "Refuse to configure %s address %s, as its valid lifetime is zero.", + network_config_source_to_string(address->source), + IN_ADDR_PREFIX_TO_STRING(address->family, &address->in_addr, address->prefixlen)); + address_cancel_requesting(address); + return 1; + } + + r = address_configure(address, &c, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure address: %m"); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 8ab5aaf0db..921b031b29 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1153,7 +1153,7 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li return 1; } -static int route_configure(const Route *route, Link *link, Request *req) { +static int route_configure(const Route *route, uint32_t lifetime_sec, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -1179,17 +1179,10 @@ static int route_configure(const Route *route, Link *link, Request *req) { if (r < 0) return r; - if (route->lifetime_usec != USEC_INFINITY) { - usec_t now_usec; - uint32_t sec; - - assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); - sec = usec_to_sec(route->lifetime_usec, now_usec); - if (sec != UINT32_MAX) { - r = sd_netlink_message_append_u32(m, RTA_EXPIRES, sec); - if (r < 0) - return r; - } + if (lifetime_sec != UINT32_MAX) { + r = sd_netlink_message_append_u32(m, RTA_EXPIRES, lifetime_sec); + if (r < 0) + return r; } if (route->ttl_propagate >= 0) { @@ -1324,6 +1317,7 @@ static int route_process_request(Request *req, Link *link, Route *route) { assert(req); assert(link); + assert(link->manager); assert(route); r = route_is_ready_to_configure(route, link); @@ -1362,7 +1356,25 @@ static int route_process_request(Request *req, Link *link, Route *route) { } } - r = route_configure(route, link, req); + usec_t now_usec; + assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); + uint32_t sec = usec_to_sec(route->lifetime_usec, now_usec); + if (sec == 0) { + log_link_debug(link, "Refuse to configure %s route with zero lifetime.", + network_config_source_to_string(route->source)); + + if (converted) + for (size_t i = 0; i < converted->n; i++) { + Route *existing; + + assert_se(route_get(link->manager, converted->links[i] ?: link, converted->routes[i], &existing) >= 0); + route_cancel_requesting(existing); + } + else + route_cancel_requesting(route); + } + + r = route_configure(route, sec, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure route: %m");