Commit 4b6f0d50 authored by Dan Williams's avatar Dan Williams
Browse files

core: fix deactivation of assumed connections on device removal (bgo #729833)

The following procedure leaves an NMActiveConnection around for a deactivated
device, which causes errors in libnm-glib clients when they cannot create the
GObject for the non-existent device of the AC.

1) allow a device which can assume connections to be activated
2) stop NM, which should leave the device's IP configuration up
3) start NM and allow it to assume the device's existing connection
4) remove the device, either by unplugging it or 'rmmod'

The device is removed by nm-manager.c::remove_device(), but the device object
is not moved to UNMANAGED state, leaving the NMActiveConnection completely
unaware the device has gone away.

The nm-manager.c::remove_device() code did not correctly handle moving a
forcibly removed (eg, by unplugging or 'ip link del' or 'rmmod') device to
the UNMANAGED state when the device was active with an assumed connection.
To fix this, make the conditions when the device should be deactivated
on removal much more explicit.

A device should be deactivated on removal if:

1) it is forcibly removed, eg by the kernel network interface being
removed due to 'ip link del' or hotplugging, or internally by NM due
to a parent WWAN interface taking priority over a WWAN ethernet interface

2) if the device cannot assume connections, in which case NetworkManager
must have activated the device and since we cannot assume the connection
on restart, we should deactivate it

3) if the device is not activated, to ensure that its IPv6 parameters
and other things get reset to the pre-NetworkManager values

https://bugzilla.gnome.org/show_bug.cgi?id=729833
parent 76aa8ce4
......@@ -727,20 +727,23 @@ remove_device (NMManager *manager, NMDevice *device, gboolean quitting)
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
if (nm_device_get_managed (device)) {
/* Leave configured interfaces up when quitting so they can be
* taken over again if NM starts up, and to ensure connectivity while
* NM is gone. Assumed connections don't get taken down even if they
* haven't been fully activated.
*/
if ( !nm_device_can_assume_connections (device)
|| (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED)
|| !quitting) {
NMActRequest *req = nm_device_get_act_request (device);
NMActRequest *req = nm_device_get_act_request (device);
gboolean unmanage = FALSE;
if (!req || !nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (req)))
nm_device_set_unmanaged (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_REMOVED);
}
/* Leave activated interfaces up when quitting so their configuration
* can be taken over when NM restarts. This ensures connectivity while
* NM is stopped. Devices which do not support connection assumption
* cannot be left up.
*/
if (!quitting) /* Forced removal; device already gone */
unmanage = TRUE;
else if (!nm_device_can_assume_connections (device))
unmanage = TRUE;
else if (!req)
unmanage = TRUE;
if (unmanage)
nm_device_set_unmanaged (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_REMOVED);
}
g_signal_handlers_disconnect_matched (device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment