summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2014-01-28 17:24:26 -0500
committerDan Winship <danw@gnome.org>2014-01-30 09:12:04 -0500
commit8123cd2410d26281b3fff85a02d42dd03422119f (patch)
tree4a7f21405778f9291fd67003693cefa5b1c171d9
parenta99ecb5405d0d2c81932adbe9b38d3dde925382c (diff)
downloadNetworkManager-8123cd2410d26281b3fff85a02d42dd03422119f.tar.gz
core: fix a crash with autoconnect masters with autoconnect slaves
If a master and at least one of its slaves were both autoconnect, NMManager would end up creating two NMActiveConnections for the master (one when the master itself is activated, and a second when the slave is activated and calls ensure_master_active_connection(). (This probably got broken when we changed it so ACs were created before their devices.) Fix this by checking for an existing master AC before creating one.
-rw-r--r--src/nm-manager.c69
1 files changed, 37 insertions, 32 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 02227f9305..be6dda0ab9 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -181,6 +181,7 @@ static gboolean find_master (NMManager *self,
NMDevice *device,
NMConnection **out_master_connection,
NMDevice **out_master_device,
+ NMActiveConnection **out_master_ac,
GError **error);
static void nm_manager_update_state (NMManager *manager);
@@ -1937,20 +1938,11 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con)
subject = nm_auth_subject_new_internal ();
active = _new_active_connection (self, connection, NULL, device, subject, &error);
if (active) {
- NMDevice *master = NULL;
- NMActRequest *master_req;
+ NMActiveConnection *master_ac;
/* If the device is a slave or VLAN, find the master ActiveConnection */
- if (find_master (self, connection, device, NULL, &master, NULL) && master) {
- master_req = nm_device_get_act_request (master);
- if (master_req)
- nm_active_connection_set_master (active, NM_ACTIVE_CONNECTION (master_req));
- else {
- nm_log_warn (LOGD_DEVICE, "(%s): master device %s not activating!",
- nm_device_get_iface (device),
- nm_device_get_iface (master));
- }
- }
+ if (find_master (self, connection, device, NULL, NULL, &master_ac, NULL) && master_ac)
+ nm_active_connection_set_master (active, master_ac);
nm_active_connection_set_assumed (active, TRUE);
nm_active_connection_export (active);
@@ -2440,6 +2432,8 @@ is_compatible_with_slave (NMConnection *master, NMConnection *slave)
* that master connection was found
* @out_master_device: on success, the master device of @connection if that
* master device was found
+ * @out_master_ac: on success, the master ActiveConnection of @connection if
+ * there already is one
* @error: the error, if an error occurred
*
* Given an #NMConnection, attempts to find its master. If @connection has
@@ -2449,19 +2443,24 @@ is_compatible_with_slave (NMConnection *master, NMConnection *slave)
* If @connection does have a master, then the outputs depend on what is in its
* #NMSettingConnection:master property:
*
- * If "master" is the ifname of an existing #NMDevice, and that device is either
- * idle or else has a compatible master connection activated or activating on it,
- * then that device will be returned in @out_master_device, and the activating
- * or activated master connection (if any) in @out_master_connection. (No
- * connection will be returned if it is not currently activating or activated.)
+ * If "master" is the ifname of an existing #NMDevice, and that device has a
+ * compatible master connection activated or activating on it, then
+ * @out_master_device, @out_master_connection, and @out_master_ac will all be
+ * set. If the device exists and is idle, only @out_master_device will be set.
+ * If the device exists and has an incompatible connection on it, an error
+ * will be returned.
*
* If "master" is the ifname of a non-existent device, then @out_master_device
* will be %NULL, and @out_master_connection will be a connection whose
- * activation would cause the creation of that device.
+ * activation would cause the creation of that device. @out_master_ac MAY be
+ * set in this case as well (if the connection has started activating, but has
+ * not yet created its device).
*
* If "master" is the UUID of a compatible master connection, then
* @out_master_connection will be the identified connection, and @out_master_device
- * will be set if it exists and the master is already active or activating on it.
+ * and/or @out_master_ac will be set if the connection is currently activating.
+ * (@out_master_device will not be set if the device exists but does not have
+ * @out_master_connection active/activating on it.)
*
* Returns: %TRUE if the master device and/or connection could be found or if
* the connection did not require a master, %FALSE otherwise
@@ -2472,6 +2471,7 @@ find_master (NMManager *self,
NMDevice *device,
NMConnection **out_master_connection,
NMDevice **out_master_device,
+ NMActiveConnection **out_master_ac,
GError **error)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
@@ -2548,6 +2548,8 @@ find_master (NMManager *self,
*out_master_connection = master_connection;
if (out_master_device)
*out_master_device = master_device;
+ if (out_master_ac && master_connection)
+ *out_master_ac = find_ac_for_connection (self, master_connection);
if (master_device || master_connection)
return TRUE;
@@ -2750,6 +2752,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
NMDevice *device, *master_device = NULL;
NMConnection *connection;
NMConnection *master_connection = NULL;
+ NMActiveConnection *master_ac = NULL;
g_return_val_if_fail (NM_IS_MANAGER (self), FALSE);
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE);
@@ -2813,15 +2816,15 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
}
/* Try to find the master connection/device if the connection has a dependency */
- if (!find_master (self, connection, device, &master_connection, &master_device, error))
+ if (!find_master (self, connection, device,
+ &master_connection, &master_device, &master_ac,
+ error))
return FALSE;
/* Ensure there's a master active connection the new connection we're
* activating can depend on.
*/
if (master_connection || master_device) {
- NMActiveConnection *master_ac = NULL;
-
if (master_connection) {
nm_log_dbg (LOGD_CORE, "Activation of '%s' requires master connection '%s'",
nm_connection_get_id (connection),
@@ -2840,17 +2843,19 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
return FALSE;
}
- master_ac = ensure_master_active_connection (self,
- nm_active_connection_get_subject (active),
- connection,
- device,
- master_connection,
- master_device,
- error);
if (!master_ac) {
- if (error)
- g_assert (*error);
- return FALSE;
+ master_ac = ensure_master_active_connection (self,
+ nm_active_connection_get_subject (active),
+ connection,
+ device,
+ master_connection,
+ master_device,
+ error);
+ if (!master_ac) {
+ if (error)
+ g_assert (*error);
+ return FALSE;
+ }
}
nm_active_connection_set_master (active, master_ac);