From 2c40a8895e9135bc0534f94f148e773e7579c0f7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 8 Sep 2021 15:37:48 +0900 Subject: [PATCH 1/6] network: simplify code a bit --- src/network/networkd-address.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index c0d4e9ae673..714fd8ccc2c 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -436,6 +436,7 @@ static int address_add(Link *link, const Address *in, Address **ret) { } static int address_update(Address *address, const Address *src) { + Link *link; bool ready; int r; @@ -443,17 +444,18 @@ static int address_update(Address *address, const Address *src) { assert(address->link); assert(src); + link = address->link; ready = address_is_ready(address); address->flags = src->flags; address->scope = src->scope; address->cinfo = src->cinfo; - if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 0; - link_update_operstate(address->link, true); - link_check_ready(address->link); + link_update_operstate(link, true); + link_check_ready(link); if (!ready && address_is_ready(address)) { if (address->callback) { @@ -463,10 +465,10 @@ static int address_update(Address *address, const Address *src) { } if (address->family == AF_INET6 && - in6_addr_is_link_local(&address->in_addr.in6) > 0 && - in6_addr_is_null(&address->link->ipv6ll_address)) { + in6_addr_is_link_local(&address->in_addr.in6) && + in6_addr_is_null(&link->ipv6ll_address)) { - r = link_ipv6ll_gained(address->link, &address->in_addr.in6); + r = link_ipv6ll_gained(link, &address->in_addr.in6); if (r < 0) return r; } From 7a8685ffefcd27b55845758bad6c022785e1044a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 8 Sep 2021 15:39:41 +0900 Subject: [PATCH 2/6] network: enable IP masquerade when address is assigned Previously, IP masquerade is enabled when configuring the address. But, the request of assigning the address may be refused by kernel. --- src/network/networkd-address.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 714fd8ccc2c..08f0982ff0f 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -454,6 +454,10 @@ static int address_update(Address *address, const Address *src) { if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 0; + r = address_set_masquerade(address, true); + if (r < 0) + return log_link_warning_errno(link, r, "Could not enable IP masquerading: %m"); + link_update_operstate(link, true); link_check_ready(link); @@ -1290,10 +1294,6 @@ int request_process_address(Request *req) { return r; } - r = address_set_masquerade(a, true); - if (r < 0) - log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m"); - return 1; } From 7657ec3eb81fed61f8ae944c818a33ffc6956560 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 8 Sep 2021 15:52:53 +0900 Subject: [PATCH 3/6] network: store IPv6LL address even if link is in failed state Otherwise, if IPv6LL is received when the link is in failed state, we may fail to reconfigure the link. --- src/network/networkd-address.c | 21 ++++++++++++--------- src/network/networkd-link.c | 19 ++++++++----------- src/network/networkd-link.h | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 08f0982ff0f..5125c60b86c 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -451,6 +451,18 @@ static int address_update(Address *address, const Address *src) { address->scope = src->scope; address->cinfo = src->cinfo; + if (address_is_ready(address) && + address->family == AF_INET6 && + in6_addr_is_link_local(&address->in_addr.in6) && + in6_addr_is_null(&link->ipv6ll_address)) { + + link->ipv6ll_address = address->in_addr.in6; + + r = link_ipv6ll_gained(link); + if (r < 0) + return r; + } + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 0; @@ -467,15 +479,6 @@ static int address_update(Address *address, const Address *src) { if (r < 0) return r; } - - if (address->family == AF_INET6 && - in6_addr_is_link_local(&address->in_addr.in6) && - in6_addr_is_null(&link->ipv6ll_address)) { - - r = link_ipv6ll_gained(link, &address->in_addr.in6); - if (r < 0) - return r; - } } return 0; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index a5a23a33b44..1f840db22bb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -701,24 +701,21 @@ static int link_acquire_dynamic_conf(Link *link) { return 0; } -int link_ipv6ll_gained(Link *link, const struct in6_addr *address) { +int link_ipv6ll_gained(Link *link) { int r; assert(link); log_link_info(link, "Gained IPv6LL"); - link->ipv6ll_address = *address; + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return 0; + + r = link_acquire_dynamic_ipv6_conf(link); + if (r < 0) + return r; + link_check_ready(link); - - if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) { - r = link_acquire_dynamic_ipv6_conf(link); - if (r < 0) { - link_enter_failed(link); - return r; - } - } - return 0; } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 79400dee2e9..19e212766e1 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -236,7 +236,7 @@ bool link_has_carrier(Link *link); bool link_ipv6_enabled(Link *link); bool link_ipv6ll_enabled(Link *link); -int link_ipv6ll_gained(Link *link, const struct in6_addr *address); +int link_ipv6ll_gained(Link *link); bool link_ipv4ll_enabled(Link *link); From 18d8a33a3797dcd5e68932a17c6fdea660ae4c1c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 8 Sep 2021 16:11:36 +0900 Subject: [PATCH 4/6] network: define Address earlier As the type is used in defining address_ready_callback_t. --- src/network/networkd-address.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 811940c1261..6b5f7ba9c49 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -14,12 +14,13 @@ #define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU +typedef struct Address Address; typedef struct Manager Manager; typedef struct Network Network; typedef struct Request Request; typedef int (*address_ready_callback_t)(Address *address); -typedef struct Address { +struct Address { Network *network; NetworkConfigSection *section; @@ -48,7 +49,7 @@ typedef struct Address { /* Called when address become ready */ address_ready_callback_t callback; -} Address; +}; const char* format_lifetime(char *buf, size_t l, uint32_t lifetime) _warn_unused_result_; /* Note: the lifetime of the compound literal is the immediately surrounding block, From 981fab5d0a62d2222dcc58e057e7bc283b47e17b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 8 Sep 2021 15:57:55 +0900 Subject: [PATCH 5/6] network: always call address ready callback if address is ready The address ready callback is used for cleaning up old addresses or routes acquired by e.g. DHCP. However, the callback was called only when the address was previously not ready. So, maybe, unnecessary addresses or routes may not be cleared. Also, this makes the callback is called slightly earlier. As it may remove several addresses or routes, and possibly changes the link state. --- src/network/networkd-address.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 5125c60b86c..1b8f52fcbfd 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -437,7 +437,6 @@ static int address_add(Link *link, const Address *in, Address **ret) { static int address_update(Address *address, const Address *src) { Link *link; - bool ready; int r; assert(address); @@ -445,7 +444,6 @@ static int address_update(Address *address, const Address *src) { assert(src); link = address->link; - ready = address_is_ready(address); address->flags = src->flags; address->scope = src->scope; @@ -470,17 +468,14 @@ static int address_update(Address *address, const Address *src) { if (r < 0) return log_link_warning_errno(link, r, "Could not enable IP masquerading: %m"); - link_update_operstate(link, true); - link_check_ready(link); - - if (!ready && address_is_ready(address)) { - if (address->callback) { - r = address->callback(address); - if (r < 0) - return r; - } + if (address_is_ready(address) && address->callback) { + r = address->callback(address); + if (r < 0) + return r; } + link_update_operstate(link, true); + link_check_ready(link); return 0; } From ecedc48b19f592b31f541eb5ae859e682100233e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 8 Sep 2021 16:18:52 +0900 Subject: [PATCH 6/6] network: do not drop IPv6LL address in link_drop_addresses() --- src/network/networkd-address.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 1b8f52fcbfd..a8856979692 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -882,7 +882,7 @@ int link_drop_foreign_addresses(Link *link) { SET_FOREACH(address, link->addresses_foreign) { /* We consider IPv6LL addresses to be managed by the kernel, or dropped in link_drop_ipv6ll_addresses() */ - if (address->family == AF_INET6 && in6_addr_is_link_local(&address->in_addr.in6) == 1) + if (address->family == AF_INET6 && in6_addr_is_link_local(&address->in_addr.in6)) continue; if (link_address_is_dynamic(link, address)) { @@ -915,8 +915,8 @@ int link_drop_addresses(Link *link) { assert(link); SET_FOREACH(address, link->addresses) { - /* we consider IPv6LL addresses to be managed by the kernel */ - if (address->family == AF_INET6 && in6_addr_is_link_local(&address->in_addr.in6) == 1 && link_ipv6ll_enabled(link)) + /* We consider IPv6LL addresses to be managed by the kernel, or dropped in link_drop_ipv6ll_addresses() */ + if (address->family == AF_INET6 && in6_addr_is_link_local(&address->in_addr.in6)) continue; k = address_remove(address, link);