]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: do not assume static addresses are configured
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 23 Jul 2020 15:52:32 +0000 (00:52 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 28 Jul 2020 17:05:05 +0000 (02:05 +0900)
link_request_set_routes() is also called when a dynamic address is
configured. At that time, static addresses may not be configured yet.

Fixes #16546.

src/network/networkd-address.c
src/network/networkd-link.c
src/network/networkd-link.h

index a848151c8b5ce6e879b3ad6d0ae8f4d807a65693..747acfe6c5e564db81e45a9547a7c2ca4c31ea19 100644 (file)
@@ -125,6 +125,7 @@ void address_free(Address *address) {
         if (address->link && !address->acd) {
                 set_remove(address->link->addresses, address);
                 set_remove(address->link->addresses_foreign, address);
+                set_remove(address->link->static_addresses, address);
                 if (address->link->dhcp_address == address)
                         address->link->dhcp_address = NULL;
                 if (address->link->dhcp_address_old == address)
index 894b55f4c5d2bf799810a4c5f5a1f6450306ef5d..47bdd2a0dc7db16f29d352c4c4f39312a6fcf1c6 100644 (file)
@@ -730,6 +730,7 @@ static Link *link_free(Link *link) {
 
         link->addresses = set_free(link->addresses);
         link->addresses_foreign = set_free(link->addresses_foreign);
+        link->static_addresses = set_free(link->static_addresses);
         link->dhcp6_addresses = set_free(link->dhcp6_addresses);
         link->dhcp6_addresses_old = set_free(link->dhcp6_addresses_old);
         link->dhcp6_pd_addresses = set_free(link->dhcp6_pd_addresses);
@@ -1057,12 +1058,13 @@ int link_request_set_routes(Link *link) {
 
         assert(link);
         assert(link->network);
-        assert(link->addresses_configured);
-        assert(link->address_messages == 0);
         assert(link->state != _LINK_STATE_INVALID);
 
         link->static_routes_configured = false;
 
+        if (!link->addresses_ready)
+                return 0;
+
         if (!link_has_carrier(link) && !link->network->configure_without_carrier)
                 /* During configuring addresses, the link lost its carrier. As networkd is dropping
                  * the addresses now, let's not configure the routes either. */
@@ -1102,7 +1104,6 @@ int link_request_set_routes(Link *link) {
 void link_check_ready(Link *link) {
         Address *a;
         Iterator i;
-        int r;
 
         assert(link);
 
@@ -1136,15 +1137,6 @@ void link_check_ready(Link *link) {
                         return;
                 }
 
-        if (!link->addresses_ready) {
-                link->addresses_ready = true;
-                r = link_request_set_routes(link);
-                if (r < 0)
-                        link_enter_failed(link);
-                log_link_debug(link, "%s(): static addresses are configured. Configuring static routes.", __func__);
-                return;
-        }
-
         if (!link->static_routes_configured) {
                 log_link_debug(link, "%s(): static routes are not configured.", __func__);
                 return;
@@ -1246,6 +1238,50 @@ static int link_request_set_neighbors(Link *link) {
         return 0;
 }
 
+static int link_set_bridge_fdb(Link *link) {
+        FdbEntry *fdb_entry;
+        int r;
+
+        LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
+                r = fdb_entry_configure(link, fdb_entry);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
+        }
+
+        return 0;
+}
+
+static int static_address_ready_callback(Address *address) {
+        Address *a;
+        Iterator i;
+        Link *link;
+
+        assert(address);
+        assert(address->link);
+
+        link = address->link;
+
+        if (!link->addresses_configured)
+                return 0;
+
+        SET_FOREACH(a, link->static_addresses, i)
+                if (!address_is_ready(a)) {
+                        _cleanup_free_ char *str = NULL;
+
+                        (void) in_addr_to_string(a->family, &a->in_addr, &str);
+                        log_link_debug(link, "an address %s/%u is not ready", strnull(str), a->prefixlen);
+                        return 0;
+                }
+
+        /* This should not be called again */
+        SET_FOREACH(a, link->static_addresses, i)
+                a->callback = NULL;
+
+        link->addresses_ready = true;
+
+        return link_request_set_routes(link);
+}
+
 static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -1271,23 +1307,50 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
                 (void) manager_rtnl_process_address(rtnl, m, link->manager);
 
         if (link->address_messages == 0) {
+                Address *a;
+
                 log_link_debug(link, "Addresses set");
                 link->addresses_configured = true;
-                link_check_ready(link);
+
+                /* When all static addresses are already ready, then static_address_ready_callback()
+                 * will not be called automatically. So, call it here. */
+                a = set_first(link->static_addresses);
+                if (!a) {
+                        log_link_warning(link, "No static address is stored.");
+                        link_enter_failed(link);
+                        return 1;
+                }
+                if (!a->callback) {
+                        log_link_warning(link, "Address ready callback is not set.");
+                        link_enter_failed(link);
+                        return 1;
+                }
+                r = a->callback(a);
+                if (r < 0)
+                        link_enter_failed(link);
         }
 
         return 1;
 }
 
-static int link_set_bridge_fdb(Link *link) {
-        FdbEntry *fdb_entry;
+static int static_address_configure(Address *address, Link *link, bool update) {
+        Address *ret;
         int r;
 
-        LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
-                r = fdb_entry_configure(link, fdb_entry);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
-        }
+        assert(address);
+        assert(link);
+
+        r = address_configure(address, link, address_handler, update, &ret);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Could not configure static address: %m");
+
+        link->address_messages++;
+
+        r = set_ensure_put(&link->static_addresses, &address_hash_ops, ret);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to store static address: %m");
+
+        ret->callback = static_address_ready_callback;
 
         return 0;
 }
@@ -1326,11 +1389,9 @@ static int link_request_set_addresses(Link *link) {
                 else
                         update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0;
 
-                r = address_configure(ad, link, address_handler, update, NULL);
+                r = static_address_configure(ad, link, update);
                 if (r < 0)
-                        return log_link_warning_errno(link, r, "Could not set addresses: %m");
-                if (r > 0)
-                        link->address_messages++;
+                        return r;
         }
 
         if (IN_SET(link->network->router_prefix_delegation,
@@ -1344,22 +1405,20 @@ static int link_request_set_addresses(Link *link) {
 
                         r = address_new(&address);
                         if (r < 0)
-                                return log_link_error_errno(link, r, "Could not allocate address: %m");
+                                return log_oom();
 
                         r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen);
                         if (r < 0)
-                                return r;
+                                return log_link_warning_errno(link, r, "Could not get RA prefix: %m");
 
                         r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
                         if (r < 0)
-                                return r;
+                                return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m");
 
                         address->family = AF_INET6;
-                        r = address_configure(address, link, address_handler, true, NULL);
+                        r = static_address_configure(address, link, true);
                         if (r < 0)
-                                return log_link_warning_errno(link, r, "Could not set addresses: %m");
-                        if (r > 0)
-                                link->address_messages++;
+                                return r;
                 }
 
         LIST_FOREACH(labels, label, link->network->address_labels) {
@@ -1370,8 +1429,7 @@ static int link_request_set_addresses(Link *link) {
                 link->address_label_messages++;
         }
 
-        /* now that we can figure out a default address for the dhcp server,
-           start it */
+        /* now that we can figure out a default address for the dhcp server, start it */
         if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) {
                 r = dhcp4_server_configure(link);
                 if (r < 0)
@@ -1381,7 +1439,10 @@ static int link_request_set_addresses(Link *link) {
 
         if (link->address_messages == 0) {
                 link->addresses_configured = true;
-                link_check_ready(link);
+                link->addresses_ready = true;
+                r = link_request_set_routes(link);
+                if (r < 0)
+                        return r;
         } else {
                 log_link_debug(link, "Setting addresses");
                 link_set_state(link, LINK_STATE_CONFIGURING);
index 3cd4a1928958076969d545899c3f879592b2d174..7f99c0f47b2ac4932fbedf4a262da3c684f4b609 100644 (file)
@@ -87,6 +87,7 @@ typedef struct Link {
 
         Set *addresses;
         Set *addresses_foreign;
+        Set *static_addresses;
         Set *neighbors;
         Set *neighbors_foreign;
         Set *routes;