From fdd44b8e000f3aaaa9f9dd1f0a8cf84f69c55881 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 12 Feb 2012 16:13:17 -0600 Subject: [PATCH] core: handle explicit device creation on connection activation If the connection describing the virtual device isn't set to autoconnect, the device may not yet have been created. In that case, create it. --- src/nm-manager.c | 75 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index d06546462a..adbd094dc4 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2432,22 +2432,71 @@ nm_manager_activate_connection (NMManager *manager, path = nm_active_connection_get_path (NM_ACTIVE_CONNECTION (vpn_connection)); } else { NMDeviceState state; + char *iface; + int master_ifindex = -1; /* Device-based connection */ - device = nm_manager_get_device_by_path (manager, device_path); - if (!device) { - g_set_error (error, - NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "%s", "Device not found"); - return NULL; - } + if (device_path) { + device = nm_manager_get_device_by_path (manager, device_path); + if (!device) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Device not found"); + return NULL; + } - state = nm_device_get_state (device); - if (state < NM_DEVICE_STATE_DISCONNECTED) { - g_set_error (error, - NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNMANAGED_DEVICE, - "%s", "Device not managed by NetworkManager or unavailable"); - return NULL; + /* If it's a virtual interface make sure the device given by the + * path matches the connection's interface details. + */ + if (connection_needs_virtual_device (connection)) { + iface = get_virtual_iface_name (manager, connection, NULL); + if (!iface) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Failed to determine connection's virtual interface name"); + return NULL; + } else if (g_strcmp0 (iface, nm_device_get_ip_iface (device)) != 0) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Device given by path did not match connection's virtual interface name"); + g_free (iface); + return NULL; + } + g_free (iface); + } + + state = nm_device_get_state (device); + if (state < NM_DEVICE_STATE_DISCONNECTED) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNMANAGED_DEVICE, + "Device not managed by NetworkManager or unavailable"); + return NULL; + } + } else { + /* Virtual connections (VLAN, bond, etc) may not specify a device + * path because the device may not be created yet, or it be given + * by the connection's properties instead. Find the device the + * connection refers to, or create it if needed. + */ + if (!connection_needs_virtual_device (connection)) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "This connection requires an existing device."); + return NULL; + } + + iface = get_virtual_iface_name (manager, connection, &master_ifindex); + if (!iface) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Failed to determine connection's virtual interface name"); + return NULL; + } + + device = find_device_by_ip_iface (manager, iface); + if (!device) { + /* Create it */ + device = system_create_virtual_device (manager, connection); + if (!device) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Failed to create virtual interface"); + return NULL; + } + } } path = internal_activate_device (manager,