summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-10-03 11:54:20 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-10-04 02:52:46 +0900
commitaf2aea8bb64b0dc42ecbe5549216eb567681a803 (patch)
tree642e29825207ed394c71bb1129beec805c96b7c6
parent0cf1fe88885bd5ae1944c331ee1a5ec80b0ddfbc (diff)
downloadsystemd-af2aea8bb64b0dc42ecbe5549216eb567681a803.tar.gz
network: ndisc: drop addresses and friends when RA with zero lifetime is received
Routers may send options with zero lifetime if previously announced information is outdated. Hence, if we receive such messages, then we need to drop relevant addresses or friends. See e.g. https://www.rfc-editor.org/rfc/rfc4861#section-12. Follow-up for 2ccada8dc4a3571468a335808fd6fe49b8c6c6dd.
-rw-r--r--src/network/networkd-address.c10
-rw-r--r--src/network/networkd-ndisc.c34
-rw-r--r--src/network/networkd-route.c10
3 files changed, 30 insertions, 24 deletions
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 60d3c6286e..259cd312c9 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -1154,7 +1154,7 @@ int link_request_address(
address_netlink_handler_t netlink_handler,
Request **ret) {
- Address *acquired, *existing;
+ Address *acquired, *existing = NULL;
int r;
assert(link);
@@ -1187,7 +1187,13 @@ int link_request_address(
address_set_broadcast(address, link);
}
- if (address_get(link, address, &existing) < 0) {
+ (void) address_get(link, address, &existing);
+
+ if (address->lifetime_valid_usec == 0)
+ /* The requested address is outdated. Let's remove it. */
+ return address_remove_and_drop(existing);
+
+ if (!existing) {
_cleanup_(address_freep) Address *tmp = NULL;
if (consume_object)
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 124c777105..f2057a2d98 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -235,9 +235,6 @@ 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 gateway lifetime from RA: %m");
- if (lifetime_sec == 0) /* not a default router */
- return 0;
-
r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
@@ -351,11 +348,6 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
- if (lifetime_valid_sec == 0) {
- log_link_debug(link, "Ignoring prefix as its valid lifetime is zero.");
- return 0;
- }
-
r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred_sec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
@@ -412,9 +404,6 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
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, &timestamp_usec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
@@ -515,9 +504,6 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
if (r < 0)
return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m");
- if (lifetime_sec == 0)
- return 0;
-
r = sd_ndisc_router_route_get_address(rt, &dst);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get route destination address: %m");
@@ -623,9 +609,6 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
- if (lifetime_sec == 0)
- return 0;
-
lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
@@ -643,6 +626,13 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
.address = a[j],
};
+ if (lifetime_usec == 0) {
+ /* The entry is outdated. */
+ free(set_remove(link->ndisc_rdnss, &d));
+ updated = true;
+ continue;
+ }
+
rdnss = set_get(link->ndisc_rdnss, &d);
if (rdnss) {
rdnss->router = router;
@@ -716,9 +706,6 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
if (r < 0)
return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
- if (lifetime_sec == 0)
- return 0;
-
lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
r = sd_ndisc_router_dnssl_get_domains(rt, &l);
@@ -741,6 +728,13 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
strcpy(NDISC_DNSSL_DOMAIN(s), *j);
+ if (lifetime_usec == 0) {
+ /* The entry is outdated. */
+ free(set_remove(link->ndisc_dnssl, s));
+ updated = true;
+ continue;
+ }
+
dnssl = set_get(link->ndisc_dnssl, s);
if (dnssl) {
dnssl->router = router;
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 2b17959ca2..514845f7c5 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -1426,7 +1426,7 @@ int link_request_route(
route_netlink_handler_t netlink_handler,
Request **ret) {
- Route *existing;
+ Route *existing = NULL;
int r;
assert(link);
@@ -1435,7 +1435,13 @@ int link_request_route(
assert(route->source != NETWORK_CONFIG_SOURCE_FOREIGN);
assert(!route_needs_convert(route));
- if (route_get(link->manager, link, route, &existing) < 0) {
+ (void) route_get(link->manager, link, route, &existing);
+
+ if (route->lifetime_usec == 0)
+ /* The requested route is outdated. Let's remove it. */
+ return route_remove_and_drop(existing);
+
+ if (!existing) {
_cleanup_(route_freep) Route *tmp = NULL;
if (consume_object)