]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-link.c
Merge pull request #34499 from YHNdnzj/sd-path-trivial-cleanup
[thirdparty/systemd.git] / src / network / networkd-link.c
index 61e0e16818e5e3c042529bfddd29b1212446465b..234e08680bfd9de2c9b08093bfad174bbe8251c4 100644 (file)
@@ -24,7 +24,7 @@
 #include "event-util.h"
 #include "fd-util.h"
 #include "fileio.h"
-#include "format-util.h"
+#include "format-ifname.h"
 #include "fs-util.h"
 #include "glyph-util.h"
 #include "logarithm.h"
@@ -252,6 +252,8 @@ static void link_free_engines(Link *link) {
 static Link *link_free(Link *link) {
         assert(link);
 
+        (void) sysctl_clear_link_shadows(link);
+
         link_ntp_settings_clear(link);
         link_dns_settings_clear(link);
 
@@ -427,8 +429,6 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) {
 }
 
 void link_enter_failed(Link *link) {
-        int r;
-
         assert(link);
 
         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
@@ -444,13 +444,8 @@ void link_enter_failed(Link *link) {
         }
 
         log_link_info(link, "Trying to reconfigure the interface.");
-        r = link_reconfigure(link, /* force = */ true);
-        if (r < 0) {
-                log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
-                goto stop;
-        }
-
-        return;
+        if (link_reconfigure(link, /* force = */ true) > 0)
+                return;
 
 stop:
         (void) link_stop_engines(link, /* may_keep_dhcp = */ false);
@@ -822,9 +817,6 @@ static int link_handle_bound_by_list(Link *link) {
 
         /* Update up or down state of interfaces which depend on this interface's carrier state. */
 
-        if (hashmap_isempty(link->bound_by_links))
-                return 0;
-
         HASHMAP_FOREACH(l, link->bound_by_links) {
                 r = link_handle_bound_to_list(l);
                 if (r < 0)
@@ -1301,9 +1293,9 @@ static int link_get_network(Link *link, Network **ret) {
                 }
 
                 log_link_full(link, warn ? LOG_WARNING : LOG_DEBUG,
-                              "found matching network '%s'%s.",
-                              network->filename,
-                              warn ? ", based on potentially unpredictable interface name" : "");
+                              "Found matching .network file%s: %s",
+                              warn ? ", based on potentially unpredictable interface name" : "",
+                              network->filename);
 
                 if (network->unmanaged)
                         return -ENOENT;
@@ -1312,23 +1304,20 @@ static int link_get_network(Link *link, Network **ret) {
                 return 0;
         }
 
-        return -ENOENT;
+        return log_link_debug_errno(link, SYNTHETIC_ERRNO(ENOENT), "No matching .network found.");
 }
 
 int link_reconfigure_impl(Link *link, bool force) {
         Network *network = NULL;
-        NetDev *netdev = NULL;
         int r;
 
         assert(link);
 
+        link_assign_netdev(link);
+
         if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
                 return 0;
 
-        r = netdev_get(link->manager, link->ifname, &netdev);
-        if (r < 0 && r != -ENOENT)
-                return r;
-
         r = link_get_network(link, &network);
         if (r < 0 && r != -ENOENT)
                 return r;
@@ -1393,9 +1382,6 @@ int link_reconfigure_impl(Link *link, bool force) {
         link_free_engines(link);
         link->network = network_unref(link->network);
 
-        netdev_unref(link->netdev);
-        link->netdev = netdev_ref(netdev);
-
         if (!network) {
                 link_set_state(link, LINK_STATE_UNMANAGED);
                 return 0;
@@ -1454,8 +1440,14 @@ int link_reconfigure(Link *link, bool force) {
                 return 0; /* 0 means no-op. */
 
         r = link_call_getlink(link, force ? link_force_reconfigure_handler : link_reconfigure_handler);
-        if (r < 0)
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
+                link_enter_failed(link);
                 return r;
+        }
+
+        if (force || link->state == LINK_STATE_FAILED)
+                link_set_state(link, LINK_STATE_INITIALIZED);
 
         return 1; /* 1 means the interface will be reconfigured. */
 }
@@ -1466,17 +1458,26 @@ typedef struct ReconfigureData {
         sd_bus_message *message;
 } ReconfigureData;
 
+static ReconfigureData* reconfigure_data_free(ReconfigureData *data) {
+        if (!data)
+                return NULL;
+
+        link_unref(data->link);
+        sd_bus_message_unref(data->message);
+
+        return mfree(data);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(ReconfigureData*, reconfigure_data_free);
+
 static void reconfigure_data_destroy_callback(ReconfigureData *data) {
         int r;
 
         assert(data);
-        assert(data->link);
         assert(data->manager);
         assert(data->manager->reloading > 0);
         assert(data->message);
 
-        link_unref(data->link);
-
         data->manager->reloading--;
         if (data->manager->reloading <= 0) {
                 r = sd_bus_reply_method_return(data->message, NULL);
@@ -1484,8 +1485,7 @@ static void reconfigure_data_destroy_callback(ReconfigureData *data) {
                         log_warning_errno(r, "Failed to send reply for 'Reload' DBus method, ignoring: %m");
         }
 
-        sd_bus_message_unref(data->message);
-        free(data);
+        reconfigure_data_free(data);
 }
 
 static int reconfigure_handler_on_bus_method_reload(sd_netlink *rtnl, sd_netlink_message *m, ReconfigureData *data) {
@@ -1496,7 +1496,7 @@ static int reconfigure_handler_on_bus_method_reload(sd_netlink *rtnl, sd_netlink
 
 int link_reconfigure_on_bus_method_reload(Link *link, sd_bus_message *message) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        _cleanup_free_ ReconfigureData *data = NULL;
+        _cleanup_(reconfigure_data_freep) ReconfigureData *data = NULL;
         int r;
 
         assert(link);
@@ -1508,19 +1508,11 @@ int link_reconfigure_on_bus_method_reload(Link *link, sd_bus_message *message) {
         if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED, LINK_STATE_LINGER))
                 return 0;
 
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, link->ifindex);
-        if (r < 0)
-                return r;
-
         data = new(ReconfigureData, 1);
-        if (!data)
-                return -ENOMEM;
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req,
-                               reconfigure_handler_on_bus_method_reload,
-                               reconfigure_data_destroy_callback, data);
-        if (r < 0)
-                return r;
+        if (!data) {
+                r = -ENOMEM;
+                goto failed;
+        }
 
         *data = (ReconfigureData) {
                 .link = link_ref(link),
@@ -1528,10 +1520,28 @@ int link_reconfigure_on_bus_method_reload(Link *link, sd_bus_message *message) {
                 .message = sd_bus_message_ref(message),
         };
 
-        link->manager->reloading++;
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, link->ifindex);
+        if (r < 0)
+                goto failed;
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req,
+                               reconfigure_handler_on_bus_method_reload,
+                               reconfigure_data_destroy_callback, data);
+        if (r < 0)
+                goto failed;
 
         TAKE_PTR(data);
+        link->manager->reloading++;
+
+        if (link->state == LINK_STATE_FAILED)
+                link_set_state(link, LINK_STATE_INITIALIZED);
+
         return 0;
+
+failed:
+        log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
+        link_enter_failed(link);
+        return r;
 }
 
 static int link_initialized_and_synced(Link *link) {
@@ -1714,6 +1724,13 @@ static int link_carrier_gained(Link *link) {
         if (r < 0)
                 log_link_warning_errno(link, r, "Failed to disable carrier lost timer, ignoring: %m");
 
+        /* Process BindCarrier= setting specified by other interfaces. This is independent of the .network
+         * file assigned to this interface, but depends on .network files assigned to other interfaces.
+         * Hence, this can and should be called earlier. */
+        r = link_handle_bound_by_list(link);
+        if (r < 0)
+                return r;
+
         /* If a wireless interface was connected to an access point, and the SSID is changed (that is,
          * both previous_ssid and ssid are non-NULL), then the connected wireless network could be
          * changed. So, always reconfigure the link. Which means e.g. the DHCP client will be
@@ -1747,10 +1764,6 @@ static int link_carrier_gained(Link *link) {
         if (r != 0)
                 return r;
 
-        r = link_handle_bound_by_list(link);
-        if (r < 0)
-                return r;
-
         if (link->iftype == ARPHRD_CAN)
                 /* let's shortcut things for CAN which doesn't need most of what's done below. */
                 return 0;
@@ -1769,25 +1782,22 @@ static int link_carrier_gained(Link *link) {
 }
 
 static int link_carrier_lost_impl(Link *link) {
-        int r, ret = 0;
+        int ret = 0;
 
         assert(link);
 
         link->previous_ssid = mfree(link->previous_ssid);
 
+        ret = link_handle_bound_by_list(link);
+
         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 0;
+                return ret;
 
         if (!link->network)
-                return 0;
+                return ret;
 
-        r = link_stop_engines(link, false);
-        if (r < 0)
-                ret = r;
-
-        r = link_drop_managed_config(link);
-        if (r < 0 && ret >= 0)
-                ret = r;
+        RET_GATHER(ret, link_stop_engines(link, false));
+        RET_GATHER(ret, link_drop_managed_config(link));
 
         return ret;
 }
@@ -1808,22 +1818,17 @@ static int link_carrier_lost_handler(sd_event_source *s, uint64_t usec, void *us
 static int link_carrier_lost(Link *link) {
         uint16_t dhcp_mtu;
         usec_t usec;
-        int r;
 
         assert(link);
 
-        r = link_handle_bound_by_list(link);
-        if (r < 0)
-                return r;
-
         if (link->iftype == ARPHRD_CAN)
                 /* let's shortcut things for CAN which doesn't need most of what's done below. */
-                return 0;
+                usec = 0;
 
-        if (!link->network)
-                return 0;
+        else if (!link->network)
+                usec = 0;
 
-        if (link->network->ignore_carrier_loss_set)
+        else if (link->network->ignore_carrier_loss_set)
                 /* If IgnoreCarrierLoss= is explicitly specified, then use the specified value. */
                 usec = link->network->ignore_carrier_loss_usec;
 
@@ -2538,7 +2543,7 @@ static int link_update_name(Link *link, sd_netlink_message *message) {
         if (link->dhcp6_client) {
                 r = sd_dhcp6_client_set_ifname(link->dhcp6_client, link->ifname);
                 if (r < 0)
-                        return log_link_debug_errno(link, r, "Failed to update interface name in DHCP6 client: %m");
+                        return log_link_debug_errno(link, r, "Failed to update interface name in DHCPv6 client: %m");
         }
 
         if (link->ndisc) {
@@ -2801,6 +2806,7 @@ int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Man
                         r = netdev_set_ifindex(netdev, message);
                         if (r < 0) {
                                 log_netdev_warning_errno(netdev, r, "Could not process new link message for netdev, ignoring: %m");
+                                netdev_enter_failed(netdev);
                                 return 0;
                         }
                 }