core: fix unmanaging of devices when quitting

When NM quits, we don't want to unmanage a device that has
an active connection and can take that connection over again when
NM starts back up.  This makes '/etc/init.d/NetworkManager restart'
work seamlessly.  All other devices get unmanaged so their
connection (and any dependent VPN connections or wpa_supplicant
processes) get terminated.  This bug caused active VPN connections
over wifi to be left running even when they didn't have IP
connectivity.

There were two bugs:

1) the NMDevice class implemented connection_match_config() for
all device subclasses, but only Ethernet devices can assume
connections at startup.  Thus the quit-time check passed for
active wifi devices too, and they weren't properly cleaned up

2) The logic for figuring out which devices to clean up after when
quitting was somewhat flawed; we want to default to unmanaging
devices and then skip that step for ones that meet specific
criteria.  Instead the code defaulted to leaving all devices active
at shutdown.
This commit is contained in:
Dan Williams
2010-08-11 17:26:33 -05:00
parent 92babdb658
commit 37c578a2a2
4 changed files with 37 additions and 24 deletions

View File

@@ -398,11 +398,13 @@ nm_device_interface_connection_match_config (NMDeviceInterface *device,
}
gboolean
nm_device_interface_can_assume_connection (NMDeviceInterface *device)
nm_device_interface_can_assume_connections (NMDeviceInterface *device)
{
g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), FALSE);
return !!NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config;
if (NM_DEVICE_INTERFACE_GET_INTERFACE (device)->can_assume_connections)
return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->can_assume_connections (device);
return FALSE;
}
void

View File

@@ -109,6 +109,8 @@ struct _NMDeviceInterface {
NMConnection * (*connection_match_config) (NMDeviceInterface *device, const GSList *specs);
gboolean (*can_assume_connections) (NMDeviceInterface *device);
void (*set_enabled) (NMDeviceInterface *device, gboolean enabled);
gboolean (*get_enabled) (NMDeviceInterface *device);
@@ -145,7 +147,7 @@ gboolean nm_device_interface_spec_match_list (NMDeviceInterface *device,
NMConnection * nm_device_interface_connection_match_config (NMDeviceInterface *device,
const GSList *connections);
gboolean nm_device_interface_can_assume_connection (NMDeviceInterface *device);
gboolean nm_device_interface_can_assume_connections (NMDeviceInterface *device);
gboolean nm_device_interface_get_enabled (NMDeviceInterface *device);

View File

@@ -159,6 +159,7 @@ static void nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason
static gboolean device_disconnect (NMDeviceInterface *device, GError **error);
static gboolean spec_match_list (NMDeviceInterface *device, const GSList *specs);
static NMConnection *connection_match_config (NMDeviceInterface *device, const GSList *connections);
static gboolean can_assume_connections (NMDeviceInterface *device);
static void nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self, int family);
@@ -196,6 +197,7 @@ device_interface_init (NMDeviceInterface *device_interface_class)
device_interface_class->disconnect = device_disconnect;
device_interface_class->spec_match_list = spec_match_list;
device_interface_class->connection_match_config = connection_match_config;
device_interface_class->can_assume_connections = can_assume_connections;
}
@@ -3310,7 +3312,7 @@ dispose (GObject *object)
/* Don't down can-assume-connection capable devices that are activated with
* a connection that can be assumed.
*/
if ( nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (self))
if ( nm_device_interface_can_assume_connections (NM_DEVICE_INTERFACE (self))
&& (nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED)) {
NMConnection *connection;
NMSettingIP4Config *s_ip4;
@@ -3868,6 +3870,14 @@ connection_match_config (NMDeviceInterface *device, const GSList *connections)
return NULL;
}
static gboolean
can_assume_connections (NMDeviceInterface *device)
{
g_return_val_if_fail (device != NULL, FALSE);
return !!NM_DEVICE_GET_CLASS (device)->connection_match_config;
}
void
nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout)
{

View File

@@ -139,8 +139,7 @@ static NMDevice *find_device_by_iface (NMManager *self, const gchar *iface);
static GSList * remove_one_device (NMManager *manager,
GSList *list,
NMDevice *device,
gboolean quitting,
gboolean force_unmanage);
gboolean quitting);
static NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi);
@@ -371,8 +370,7 @@ modem_added (NMModemManager *modem_manager,
priv->devices = remove_one_device (NM_MANAGER (user_data),
priv->devices,
replace_device,
FALSE,
TRUE);
FALSE);
}
/* Give Bluetooth DUN devices first chance to claim the modem */
@@ -471,20 +469,22 @@ static GSList *
remove_one_device (NMManager *manager,
GSList *list,
NMDevice *device,
gboolean quitting,
gboolean force_unmanage)
gboolean quitting)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
if (nm_device_get_managed (device)) {
gboolean unmanage = !quitting;
/* When quitting, we want to leave up interfaces & connections
* that can be taken over again (ie, "assumed") when NM restarts
* so that '/etc/init.d/NetworkManager restart' will not distrupt
* networking for interfaces that support connection assumption.
* All other devices get unmanaged when NM quits so that their
* connections get torn down and the interface is deactivated.
*/
/* Don't unmanage active assume-connection-capable devices at shutdown */
if ( nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (device))
&& nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
unmanage = FALSE;
if (unmanage || force_unmanage)
if ( !nm_device_interface_can_assume_connections (NM_DEVICE_INTERFACE (device))
|| (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED)
|| !quitting)
nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
}
@@ -518,7 +518,7 @@ modem_removed (NMModemManager *modem_manager,
/* Otherwise remove the standalone modem */
found = nm_manager_get_device_by_udi (self, nm_modem_get_path (modem));
if (found)
priv->devices = remove_one_device (self, priv->devices, found, FALSE, TRUE);
priv->devices = remove_one_device (self, priv->devices, found, FALSE);
}
static void
@@ -2069,7 +2069,7 @@ add_device (NMManager *self, NMDevice *device)
/* Check if we should assume the device's active connection by matching its
* config with an existing system connection.
*/
if (nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (device))) {
if (nm_device_interface_can_assume_connections (NM_DEVICE_INTERFACE (device))) {
GSList *connections = NULL;
g_hash_table_iter_init (&iter, priv->system_connections);
@@ -2229,7 +2229,7 @@ bluez_manager_resync_devices (NMManager *self)
priv->devices = keep;
while (g_slist_length (gone))
gone = remove_one_device (self, gone, NM_DEVICE (gone->data), FALSE, TRUE);
gone = remove_one_device (self, gone, NM_DEVICE (gone->data), FALSE);
} else {
g_slist_free (keep);
g_slist_free (gone);
@@ -2298,7 +2298,7 @@ bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr,
NMDevice *device = NM_DEVICE (iter->data);
if (!strcmp (nm_device_get_udi (device), object_path)) {
priv->devices = remove_one_device (self, priv->devices, device, FALSE, TRUE);
priv->devices = remove_one_device (self, priv->devices, device, FALSE);
break;
}
}
@@ -2367,7 +2367,7 @@ udev_device_removed_cb (NMUdevManager *manager,
ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX");
device = find_device_by_ifindex (self, ifindex);
if (device)
priv->devices = remove_one_device (self, priv->devices, device, FALSE, TRUE);
priv->devices = remove_one_device (self, priv->devices, device, FALSE);
}
static void
@@ -4065,8 +4065,7 @@ dispose (GObject *object)
priv->devices = remove_one_device (manager,
priv->devices,
NM_DEVICE (priv->devices->data),
TRUE,
FALSE);
TRUE);
}
user_proxy_cleanup (manager, FALSE);