diff options
Diffstat (limited to 'src/devices/nm-device.c')
| -rw-r--r-- | src/devices/nm-device.c | 166 |
1 files changed, 107 insertions, 59 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 529b3cd8..dde9af94 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1195,17 +1195,67 @@ nm_device_master_release_one_slave (NMDevice *self, NMDevice *slave, gboolean co static gboolean can_unmanaged_external_down (NMDevice *self) { - return nm_device_is_software (self) && !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned; + return !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned + && nm_device_is_software (self); } -static void -update_dynamic_ip_setup (NMDevice *self) +static NMUnmanFlagOp +is_unmanaged_external_down (NMDevice *self, gboolean consider_can) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if ( consider_can + && !NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) + return NM_UNMAN_FLAG_OP_FORGET; + + /* Manage externally-created software interfaces only when they are IFF_UP */ + if ( priv->ifindex <= 0 + || !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, 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 + * from the transition to UNAVAILABLE. + */ + nm_device_queue_recheck_assume (self); + } + + nm_device_set_unmanaged_by_flags (self, + NM_UNMANAGED_EXTERNAL_DOWN, + ext_flags, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); +} + +void +nm_device_update_dynamic_ip_setup (NMDevice *self) +{ + NMDevicePrivate *priv; GError *error; gconstpointer addr; size_t addr_length; + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_hash_table_remove_all (priv->ip6_saved_properties); if (priv->dhcp4_client) { @@ -1295,7 +1345,7 @@ carrier_changed (NMDevice *self, gboolean carrier) * tagged for carrier ignore) ensure that when the carrier appears we * renew DHCP leases and such. */ - update_dynamic_ip_setup (self); + nm_device_update_dynamic_ip_setup (self); } } else { if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) { @@ -1422,7 +1472,6 @@ device_link_changed (NMDevice *self) NMPlatformLink info; const NMPlatformLink *pllink; int ifindex; - gboolean was_up; priv->device_link_changed_id = 0; @@ -1493,25 +1542,21 @@ device_link_changed (NMDevice *self) /* Update DHCP, etc, if needed */ if (ip_ifname_changed) - update_dynamic_ip_setup (self); + nm_device_update_dynamic_ip_setup (self); - was_up = priv->up; priv->up = NM_FLAGS_HAS (info.n_ifi_flags, IFF_UP); - if ( priv->ifindex > 0 - && info.initialized + if ( info.initialized && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { NMDeviceStateReason reason; nm_device_set_unmanaged_by_user_udev (self); - /* If the devices that need an external IFF_UP go managed below, - * it means they're already up. In that case we should use an "assumed" - * reason to prevent the cleanup sequence from being run on transition - * from "unmanaged" to "unavailable". */ - if ( priv->up - && !nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN) - && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) { + /* If the device is a external-down candidated but no longer has external + * down set, we must clear the platform-unmanaged flag with reason + * "assumed". */ + if ( nm_device_get_unmanaged_mask (self, NM_UNMANAGED_EXTERNAL_DOWN) + && !nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)) { /* Ensure the assume check is queued before any queued state changes * from the transition to UNAVAILABLE. */ @@ -1523,35 +1568,7 @@ device_link_changed (NMDevice *self) nm_device_set_unmanaged_by_flags (self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); } - if ( priv->ifindex > 0 - && priv->up != was_up - && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) { - /* Manage externally-created software interfaces only when they are IFF_UP */ - if ( priv->up - && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)) { - /* Ensure the assume check is queued before any queued state changes - * from the transition to UNAVAILABLE. - */ - nm_device_queue_recheck_assume (self); - } - - /* In case of @priv->up, resetting the EXTERNAL_DOWN flag may change the device's - * state to UNAVAILABLE. To ensure that the state change doesn't touch - * the device before assumption occurs, pass NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED - * as the reason. - * - * In case of !@priv->up, and the device is already unmanaged for other reasons, the - * state-change-reason has no effect. - * If the device is managed for an explict user-request, the state-change-reason - * also has no effect, because the device stays managed. - * - * The state-change-reason only has effect if the device was assumed - * and is now to be unmanaged. */ - nm_device_set_unmanaged_by_flags (self, - NM_UNMANAGED_EXTERNAL_DOWN, - !priv->up, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - } + set_unmanaged_external_down (self, FALSE); device_recheck_slave_status (self, &info); return G_SOURCE_REMOVE; @@ -1580,7 +1597,7 @@ device_ip_link_changed (NMDevice *self) priv->ip_iface = g_strdup (pllink->name); _notify (self, PROP_IP_IFACE); - update_dynamic_ip_setup (self); + nm_device_update_dynamic_ip_setup (self); } return G_SOURCE_REMOVE; } @@ -1921,12 +1938,11 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) klass->realize_start_notify (self, plink); - /* Do not manage externally created software devices until they are IFF_UP */ - if ( priv->ifindex > 0 - && plink - && !priv->up - && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) - nm_device_set_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE); + /* Do not manage externally created software devices until they are IFF_UP + * or have IP addressing */ + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_EXTERNAL_DOWN, + is_unmanaged_external_down (self, TRUE)); /* Unmanaged the loopback device with an explicit NM_UNMANAGED_LOOPBACK flag. * Later we might want to manage 'lo' too. Currently that doesn't work because @@ -2569,6 +2585,18 @@ nm_device_removed (NMDevice *self) * Release the slave from master, but don't touch the device. */ nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } + + /* Clean up IP configs; this does not actually deconfigure the + * interface, it just clears the configuration to which policy + * is reacting via NM_DEVICE_IP4_CONFIG_CHANGED/NM_DEVICE_IP6_CONFIG_CHANGED + * signal. As NMPolicy registered the NMIPxConfig instances in NMDnsManager, + * these would be leaked otherwise. */ + priv->default_route.v4_has = FALSE; + priv->default_route.v4_is_assumed = TRUE; + nm_device_set_ip4_config (self, NULL, 0, FALSE, FALSE, NULL); + priv->default_route.v6_has = FALSE; + priv->default_route.v6_is_assumed = TRUE; + nm_device_set_ip6_config (self, NULL, FALSE, FALSE, NULL); } static gboolean @@ -3050,8 +3078,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; } /** @@ -8869,6 +8896,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; } @@ -8923,6 +8952,8 @@ queued_ip6_config_change (gpointer user_data) g_object_unref (self); + set_unmanaged_external_down (self, TRUE); + return FALSE; } @@ -9124,6 +9155,24 @@ nm_device_get_managed (NMDevice *self, gboolean for_user_request) } /** + * nm_device_get_unmanaged_mask: + * @self: the #NMDevice + * @flag: the unmanaged flags to check. + * + * Return the unmanaged flags mask set on this device. + * + * Returns: the flags of the device ( & @flag) + */ +NMUnmanagedFlags +nm_device_get_unmanaged_mask (NMDevice *self, NMUnmanagedFlags flag) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NM_UNMANAGED_NONE); + g_return_val_if_fail (flag != NM_UNMANAGED_NONE, NM_UNMANAGED_NONE); + + return NM_DEVICE_GET_PRIVATE (self)->unmanaged_mask & flag; +} + +/** * nm_device_get_unmanaged_flags: * @self: the #NMDevice * @flag: the unmanaged flags to check. @@ -9135,8 +9184,8 @@ nm_device_get_managed (NMDevice *self, gboolean for_user_request) NMUnmanagedFlags nm_device_get_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flag) { - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - g_return_val_if_fail (flag != NM_UNMANAGED_NONE, FALSE); + g_return_val_if_fail (NM_IS_DEVICE (self), NM_UNMANAGED_NONE); + g_return_val_if_fail (flag != NM_UNMANAGED_NONE, NM_UNMANAGED_NONE); return NM_DEVICE_GET_PRIVATE (self)->unmanaged_flags & flag; } @@ -9943,7 +9992,6 @@ static void _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE; priv->default_route.v4_has = FALSE; priv->default_route.v6_has = FALSE; @@ -9968,8 +10016,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) /* Clean up IP configs; this does not actually deconfigure the * interface; the caller must flush routes and addresses explicitly. */ - nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE, &ignored); - nm_device_set_ip6_config (self, NULL, TRUE, TRUE, &ignored); + nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE, NULL); + nm_device_set_ip6_config (self, NULL, TRUE, TRUE, NULL); g_clear_object (&priv->con_ip4_config); g_clear_object (&priv->dev_ip4_config); g_clear_object (&priv->ext_ip4_config); |