diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 50858333aa..619eda9bba 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1210,20 +1210,26 @@ is_unmanaged_external_down (NMDevice *self, gboolean consider_can) /* Manage externally-created software interfaces only when they are IFF_UP */ if ( priv->ifindex <= 0 - || !priv->up) + || !priv->up + || !nm_platform_link_can_assume (NM_PLATFORM_GET, priv->ifindex)) return NM_UNMAN_FLAG_OP_SET_UNMANAGED; return NM_UNMAN_FLAG_OP_SET_MANAGED; } static void -set_unmanaged_external_down (NMDevice *self) +set_unmanaged_external_down (NMDevice *self, gboolean only_if_unmanaged) { NMUnmanFlagOp ext_flags; if (!nm_device_get_unmanaged_mask (self, NM_UNMANAGED_EXTERNAL_DOWN)) return; + if (only_if_unmanaged) { + if (!nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)) + return; + } + ext_flags = is_unmanaged_external_down (self, FALSE); if (ext_flags != NM_UNMAN_FLAG_OP_SET_UNMANAGED) { /* Ensure the assume check is queued before any queued state changes @@ -1562,7 +1568,7 @@ device_link_changed (NMDevice *self) nm_device_set_unmanaged_by_flags (self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); } - set_unmanaged_external_down (self); + set_unmanaged_external_down (self, FALSE); device_recheck_slave_status (self, &info); return G_SOURCE_REMOVE; @@ -3060,8 +3066,7 @@ nm_device_check_slave_connection_compatible (NMDevice *self, NMConnection *slave static gboolean nm_device_can_assume_connections (NMDevice *self) { - return !!NM_DEVICE_GET_CLASS (self)->update_connection - && !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned; + return !!NM_DEVICE_GET_CLASS (self)->update_connection; } /** @@ -8879,6 +8884,8 @@ queued_ip4_config_change (gpointer user_data) update_ip4_config (self, FALSE); g_object_unref (self); + set_unmanaged_external_down (self, TRUE); + return FALSE; } @@ -8933,6 +8940,8 @@ queued_ip6_config_change (gpointer user_data) g_object_unref (self); + set_unmanaged_external_down (self, TRUE); + return FALSE; } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 14301598bf..3282e698ce 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -5128,6 +5128,49 @@ wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean ru /******************************************************************/ +static gboolean +link_can_assume (NMPlatform *platform, int ifindex) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + NMPCacheId cache_id; + const NMPlatformObject *const *objs; + guint i, len; + const NMPObject *link; + + if (ifindex <= 0) + return FALSE; + + link = cache_lookup_link (platform, ifindex); + if (!link) + return FALSE; + + if (!NM_FLAGS_HAS (link->link.n_ifi_flags, IFF_UP)) + return FALSE; + + if (link->link.master > 0) + return TRUE; + + if (nmp_cache_lookup_multi (priv->cache, + nmp_cache_id_init_addrroute_visible_by_ifindex (&cache_id, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex), + NULL)) + return TRUE; + + objs = nmp_cache_lookup_multi (priv->cache, + nmp_cache_id_init_addrroute_visible_by_ifindex (&cache_id, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex), + &len); + if (objs) { + for (i = 0; i < len; i++) { + const NMPlatformIP6Address *a = (NMPlatformIP6Address *) objs[i]; + + if (!IN6_IS_ADDR_LINKLOCAL (&a->address)) + return TRUE; + } + } + return FALSE; +} + +/******************************************************************/ + static guint32 mesh_get_channel (NMPlatform *platform, int ifindex) { @@ -6218,6 +6261,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->link_enslave = link_enslave; platform_class->link_release = link_release; + platform_class->link_can_assume = link_can_assume; + platform_class->vlan_add = vlan_add; platform_class->link_vlan_change = link_vlan_change; platform_class->link_vxlan_add = link_vxlan_add; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index d5ee48d49f..5a399b316a 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1378,6 +1378,18 @@ nm_platform_link_get_master (NMPlatform *self, int slave) /*****************************************************************************/ +gboolean +nm_platform_link_can_assume (NMPlatform *self, int ifindex) +{ + _CHECK_SELF (self, klass, FALSE); + + if (klass->link_can_assume) + return klass->link_can_assume (self, ifindex); + g_return_val_if_reached (FALSE); +} + +/*****************************************************************************/ + /** * nm_platform_link_get_lnk: * @self: the platform instance diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 8c97f7668a..15bd2fdeef 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -528,6 +528,8 @@ typedef struct { gboolean (*link_enslave) (NMPlatform *, int master, int slave); gboolean (*link_release) (NMPlatform *, int master, int slave); + gboolean (*link_can_assume) (NMPlatform *, int ifindex); + gboolean (*vlan_add) (NMPlatform *, const char *name, int parent, int vlanid, guint32 vlanflags, const NMPlatformLink **out_link); gboolean (*link_vlan_change) (NMPlatform *self, int ifindex, @@ -717,6 +719,8 @@ gboolean nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex gconstpointer nm_platform_link_get_address (NMPlatform *self, int ifindex, size_t *length); int nm_platform_link_get_master (NMPlatform *self, int slave); +gboolean nm_platform_link_can_assume (NMPlatform *self, int ifindex); + gboolean nm_platform_link_get_unmanaged (NMPlatform *self, int ifindex, gboolean *unmanaged); gboolean nm_platform_link_supports_slaves (NMPlatform *self, int ifindex); const char *nm_platform_link_get_type_name (NMPlatform *self, int ifindex);