/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* Make sure the net/if.h header is included before any linux/ one */
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if.h>
assert(ret);
if (link->network && operational_state_range_is_valid(&link->network->required_operstate_for_online))
+ /* If explicitly specified, use it as is. */
*ret = link->network->required_operstate_for_online;
else if (link->iftype == ARPHRD_CAN)
+ /* CAN devices do not support addressing, hence defaults to 'carrier'. */
*ret = (const LinkOperationalStateRange) {
.min = LINK_OPERSTATE_CARRIER,
.max = LINK_OPERSTATE_CARRIER,
};
+ else if (link->network && link->network->bond)
+ /* Bonding slaves do not support addressing. */
+ *ret = (const LinkOperationalStateRange) {
+ .min = LINK_OPERSTATE_ENSLAVED,
+ .max = LINK_OPERSTATE_ENSLAVED,
+ };
+ else if (STRPTR_IN_SET(link->kind, "batadv", "bond", "bridge", "vrf"))
+ /* Some of slave interfaces may be offline. */
+ *ret = (const LinkOperationalStateRange) {
+ .min = LINK_OPERSTATE_DEGRADED_CARRIER,
+ .max = LINK_OPERSTATE_ROUTABLE,
+ };
else
*ret = LINK_OPERSTATE_RANGE_DEFAULT;
}
+AddressFamily link_required_family_for_online(Link *link) {
+ assert(link);
+
+ if (link->network && link->network->required_family_for_online >= 0)
+ return link->network->required_family_for_online;
+
+ if (link->network && operational_state_range_is_valid(&link->network->required_operstate_for_online))
+ /* If RequiredForOnline= is explicitly specified, defaults to no. */
+ return ADDRESS_FAMILY_NO;
+
+ if (STRPTR_IN_SET(link->kind, "batadv", "bond", "bridge", "vrf"))
+ /* As the minimum required operstate for master interfaces is 'degraded-carrier',
+ * we should request an address assigned to the link for backward compatibility. */
+ return ADDRESS_FAMILY_YES;
+
+ return ADDRESS_FAMILY_NO;
+}
+
bool link_ipv6_enabled(Link *link) {
assert(link);
link_ntp_settings_clear(link);
link_dns_settings_clear(link);
- link->routes = set_free(link->routes);
link->neighbors = set_free(link->neighbors);
link->addresses = set_free(link->addresses);
link->qdiscs = set_free(link->qdiscs);
free(link->driver);
unlink_and_free(link->lease_file);
- unlink_and_free(link->lldp_file);
unlink_and_free(link->state_file);
sd_device_unref(link->dev);
* Note, ignore NDisc when ConfigureWithoutCarrier= is enabled, as IPv6AcceptRA= is enabled by default. */
if (!link_ipv4ll_enabled(link) && !link_dhcp4_enabled(link) &&
!link_dhcp6_enabled(link) && !link_dhcp_pd_is_enabled(link) &&
- (link->network->configure_without_carrier || !link_ipv6_accept_ra_enabled(link)))
+ (link->network->configure_without_carrier || !link_ndisc_enabled(link)))
goto ready;
bool ipv4ll_ready =
(!link->network->dhcp_pd_assign ||
link_check_addresses_ready(link, NETWORK_CONFIG_SOURCE_DHCP_PD));
bool ndisc_ready =
- link_ipv6_accept_ra_enabled(link) && link->ndisc_configured &&
- (!link->network->ipv6_accept_ra_use_autonomous_prefix ||
+ link_ndisc_enabled(link) && link->ndisc_configured &&
+ (!link->network->ndisc_use_autonomous_prefix ||
link_check_addresses_ready(link, NETWORK_CONFIG_SOURCE_NDISC));
/* If the uplink for PD is self, then request the corresponding DHCP protocol is also ready. */
if (dhcp_pd_is_uplink(link, link, /* accept_auto = */ false)) {
if (link_dhcp4_enabled(link) && link->network->dhcp_use_6rd &&
sd_dhcp_lease_has_6rd(link->dhcp_lease)) {
- if (!dhcp4_ready)
+ if (!link->dhcp4_configured)
return (void) log_link_debug(link, "%s(): DHCPv4 6rd prefix is assigned, but DHCPv4 protocol is not finished yet.", __func__);
if (!dhcp_pd_ready)
return (void) log_link_debug(link, "%s(): DHCPv4 is finished, but prefix acquired by DHCPv4-6rd is not assigned yet.", __func__);
if (link_dhcp6_enabled(link) && link->network->dhcp6_use_pd_prefix &&
sd_dhcp6_lease_has_pd_prefix(link->dhcp6_lease)) {
- if (!dhcp6_ready)
+ if (!link->dhcp6_configured)
return (void) log_link_debug(link, "%s(): DHCPv6 IA_PD prefix is assigned, but DHCPv6 protocol is not finished yet.", __func__);
if (!dhcp_pd_ready)
return (void) log_link_debug(link, "%s(): DHCPv6 is finished, but prefix acquired by DHCPv6 IA_PD is not assigned yet.", __func__);
log_link_debug(link, "Acquiring IPv4 link-local address.");
}
- if (link->dhcp_server) {
- r = sd_dhcp_server_start(link->dhcp_server);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not start DHCP server: %m");
- }
+ r = link_start_dhcp4_server(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not start DHCP server: %m");
r = ipv4acd_start(link);
if (r < 0)
RET_GATHER(ret, nexthop_remove(nexthop, link->manager));
break;
}
+ case REQUEST_TYPE_ROUTE: {
+ Route *route = ASSERT_PTR(req->userdata);
+
+ if (route_get(link->manager, route, NULL) < 0)
+ RET_GATHER(ret, route_remove(route, link->manager));
+ break;
+ }
default:
;
}
assert(link);
assert(link->manager);
- r = link_drop_managed_routes(link);
-
- RET_GATHER(r, link_drop_managed_nexthops(link));
- RET_GATHER(r, link_drop_managed_addresses(link));
- RET_GATHER(r, link_drop_managed_neighbors(link));
- RET_GATHER(r, link_drop_managed_routing_policy_rules(link));
+ r = link_drop_static_routes(link);
+ RET_GATHER(r, link_drop_static_nexthops(link));
+ RET_GATHER(r, link_drop_static_addresses(link));
+ RET_GATHER(r, link_drop_static_neighbors(link));
+ RET_GATHER(r, link_drop_static_routing_policy_rules(link));
return r;
}
return 1; /* 1 means the interface will be reconfigured. */
}
+typedef struct ReconfigureData {
+ Link *link;
+ Manager *manager;
+ sd_bus_message *message;
+} ReconfigureData;
+
+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);
+ if (r < 0)
+ log_warning_errno(r, "Failed to send reply for 'Reload' DBus method, ignoring: %m");
+ }
+
+ sd_bus_message_unref(data->message);
+ free(data);
+}
+
+static int reconfigure_handler_on_bus_method_reload(sd_netlink *rtnl, sd_netlink_message *m, ReconfigureData *data) {
+ assert(data);
+ assert(data->link);
+ return link_reconfigure_handler_internal(rtnl, m, data->link, /* force = */ false);
+}
+
+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;
+ int r;
+
+ assert(link);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+ assert(message);
+
+ /* See comments in link_reconfigure() above. */
+ 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;
+
+ *data = (ReconfigureData) {
+ .link = link_ref(link),
+ .manager = link->manager,
+ .message = sd_bus_message_ref(message),
+ };
+
+ link->manager->reloading++;
+
+ TAKE_PTR(data);
+ return 0;
+}
+
static int link_initialized_and_synced(Link *link) {
int r;
return 0;
}
- r = sd_device_get_is_initialized(device);
+ r = device_is_processed(device);
if (r < 0)
- return log_link_warning_errno(link, r, "Could not determine whether the device is initialized: %m");
+ return log_link_warning_errno(link, r, "Could not determine whether the device is processed by udevd: %m");
if (r == 0) {
/* not yet ready */
log_link_debug(link, "link pending udev initialization...");
/* We set the ipv6 mtu after the device mtu, but the kernel resets
* ipv6 mtu on NETDEV_UP, so we need to reset it. */
- r = link_set_ipv6_mtu(link);
+ r = link_set_ipv6_mtu(link, LOG_INFO);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 MTU, ignoring: %m");
online_state = LINK_ONLINE_STATE_OFFLINE;
else {
- AddressFamily required_family = link->network->required_family_for_online;
+ AddressFamily required_family = link_required_family_for_online(link);
bool needs_ipv4 = required_family & ADDRESS_FAMILY_IPV4;
bool needs_ipv6 = required_family & ADDRESS_FAMILY_IPV6;
link->mtu = mtu;
+ if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
+ /* The kernel resets IPv6 MTU after changing device MTU. So, we need to re-set IPv6 MTU again. */
+ r = link_set_ipv6_mtu(link, LOG_INFO);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to set IPv6 MTU, ignoring: %m");
+ }
+
if (link->dhcp_client) {
r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
if (r < 0)
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) {
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_drop_or_unref);
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
- _cleanup_free_ char *ifname = NULL, *kind = NULL, *state_file = NULL, *lease_file = NULL, *lldp_file = NULL;
+ _cleanup_free_ char *ifname = NULL, *kind = NULL, *state_file = NULL, *lease_file = NULL;
_cleanup_(link_drop_or_unrefp) Link *link = NULL;
unsigned short iftype;
int r, ifindex;
if (asprintf(&lease_file, "/run/systemd/netif/leases/%d", ifindex) < 0)
return log_oom_debug();
-
- if (asprintf(&lldp_file, "/run/systemd/netif/lldp/%d", ifindex) < 0)
- return log_oom_debug();
}
link = new(Link, 1);
.state_file = TAKE_PTR(state_file),
.lease_file = TAKE_PTR(lease_file),
- .lldp_file = TAKE_PTR(lldp_file),
.n_dns = UINT_MAX,
.dns_default_route = -1,