#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"
static Link *link_free(Link *link) {
assert(link);
+ (void) sysctl_clear_link_shadows(link);
+
link_ntp_settings_clear(link);
link_dns_settings_clear(link);
}
void link_enter_failed(Link *link) {
- int r;
-
assert(link);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
}
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);
/* 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)
}
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;
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;
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;
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. */
}
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);
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) {
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);
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),
.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) {
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
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;
}
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;
}
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;
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) {
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;
}
}