summaryrefslogtreecommitdiff
path: root/src/nm-manager.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2015-07-14 19:38:58 +0200
committerMichael Biebl <biebl@debian.org>2015-07-14 19:38:58 +0200
commit50a58f0fabd8a34c1b6108a107e08abe3c1ccd24 (patch)
tree6790165f39daee79e2b6c6617483320613493367 /src/nm-manager.c
parentf408e27bccfacf347605a8d98649975a68f38a17 (diff)
Imported Upstream version 1.0.4upstream/1.0.4
Diffstat (limited to 'src/nm-manager.c')
-rw-r--r--src/nm-manager.c1053
1 files changed, 510 insertions, 543 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 0fa88d1d8..080cdb8b2 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -26,8 +26,6 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <dbus/dbus-glib.h>
#include <gio/gio.h>
@@ -129,8 +127,6 @@ static NMActiveConnection *_new_active_connection (NMManager *self,
static void policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data);
-static NMDevice *find_device_by_ip_iface (NMManager *self, const gchar *iface);
-
static void rfkill_change (const char *desc, RfKillType rtype, gboolean enabled);
static gboolean find_master (NMManager *self,
@@ -161,25 +157,22 @@ typedef struct {
char *state_file;
GSList *active_connections;
+ GSList *authorizing_connections;
guint ac_cleanup_id;
NMActiveConnection *primary_connection;
NMActiveConnection *activating_connection;
GSList *devices;
NMState state;
+ NMConfig *config;
NMConnectivity *connectivity;
- int ignore_link_added_cb;
-
NMPolicy *policy;
NMDBusManager *dbus_mgr;
gboolean prop_filter_added;
NMRfkillManager *rfkill_mgr;
- /* List of NMDeviceFactoryFunc pointers sorted in priority order */
- GSList *factories;
-
NMSettings *settings;
char *hostname;
@@ -285,7 +278,8 @@ active_connection_remove (NMManager *self, NMActiveConnection *active)
g_object_unref (active);
- if (connection) {
+ if ( connection
+ && nm_settings_has_connection (priv->settings, connection)) {
nm_log_dbg (LOGD_DEVICE, "Assumed connection disconnected. Deleting generated connection '%s' (%s)",
nm_connection_get_id (connection), nm_connection_get_uuid (connection));
nm_settings_connection_delete (NM_SETTINGS_CONNECTION (connection), NULL, NULL);
@@ -463,20 +457,18 @@ active_connection_get_by_path (NMManager *manager, const char *path)
/************************************************************************/
-static NMDevice *
-nm_manager_get_device_by_udi (NMManager *manager, const char *udi)
+static void
+_config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeFlags changes, NMConfigData *old_data, NMManager *self)
{
- GSList *iter;
-
- g_return_val_if_fail (udi != NULL, NULL);
-
- for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
- if (!strcmp (nm_device_get_udi (NM_DEVICE (iter->data)), udi))
- return NM_DEVICE (iter->data);
- }
- return NULL;
+ g_object_set (NM_MANAGER_GET_PRIVATE (self)->connectivity,
+ NM_CONNECTIVITY_URI, nm_config_data_get_connectivity_uri (config_data),
+ NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data),
+ NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data),
+ NULL);
}
+/************************************************************************/
+
static NMDevice *
nm_manager_get_device_by_path (NMManager *manager, const char *path)
{
@@ -506,6 +498,50 @@ nm_manager_get_device_by_ifindex (NMManager *manager, int ifindex)
return NULL;
}
+static NMDevice *
+find_device_by_hw_addr (NMManager *manager, const char *hwaddr)
+{
+ GSList *iter;
+ const char *device_addr;
+
+ g_return_val_if_fail (hwaddr != NULL, NULL);
+
+ if (nm_utils_hwaddr_valid (hwaddr, -1)) {
+ for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
+ device_addr = nm_device_get_hw_address (NM_DEVICE (iter->data));
+ if (device_addr && nm_utils_hwaddr_matches (hwaddr, -1, device_addr, -1))
+ return NM_DEVICE (iter->data);
+ }
+ }
+ return NULL;
+}
+
+static NMDevice *
+find_device_by_ip_iface (NMManager *self, const gchar *iface)
+{
+ GSList *iter;
+
+ g_return_val_if_fail (iface != NULL, NULL);
+
+ for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = g_slist_next (iter)) {
+ if (g_strcmp0 (nm_device_get_ip_iface (NM_DEVICE (iter->data)), iface) == 0)
+ return NM_DEVICE (iter->data);
+ }
+ return NULL;
+}
+
+static NMDevice *
+find_device_by_iface (NMManager *self, const gchar *iface)
+{
+ GSList *iter;
+
+ for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = g_slist_next (iter)) {
+ if (g_strcmp0 (nm_device_get_iface (NM_DEVICE (iter->data)), iface) == 0)
+ return NM_DEVICE (iter->data);
+ }
+ return NULL;
+}
+
static gboolean
manager_sleeping (NMManager *self)
{
@@ -834,109 +870,56 @@ nm_manager_get_state (NMManager *manager)
return NM_MANAGER_GET_PRIVATE (manager)->state;
}
-/*******************************************************************/
-/* Settings stuff via NMSettings */
-/*******************************************************************/
+/***************************/
static NMDevice *
-get_device_from_hwaddr (NMManager *self, const char *setting_mac)
+find_parent_device_for_connection (NMManager *self, NMConnection *connection)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
- const char *device_mac;
+ NMDeviceFactory *factory;
+ const char *parent_name = NULL;
+ NMConnection *parent_connection;
+ NMDevice *parent, *first_compatible = NULL;
GSList *iter;
- if (!setting_mac)
+ factory = nm_device_factory_manager_find_factory_for_connection (connection);
+ if (!factory)
return NULL;
- for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
- NMDevice *device = iter->data;
-
- device_mac = nm_device_get_hw_address (iter->data);
- if (!device_mac)
- continue;
- if (nm_utils_hwaddr_matches (setting_mac, -1, device_mac, -1))
- return device;
- }
- return NULL;
-}
-
-static NMDevice *
-find_vlan_parent (NMManager *self,
- NMConnection *connection)
-{
- NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
- NMSettingVlan *s_vlan;
- NMSettingWired *s_wired;
- NMConnection *parent_connection;
- const char *parent_iface;
- NMDevice *parent = NULL;
- const char *setting_mac;
- GSList *iter;
+ parent_name = nm_device_factory_get_connection_parent (factory, connection);
+ if (!parent_name)
+ return NULL;
- /* The 'parent' property could be given by an interface name, a
- * connection UUID, or the MAC address of an NMSettingWired.
- */
- s_vlan = nm_connection_get_setting_vlan (connection);
- g_return_val_if_fail (s_vlan != NULL, NULL);
-
- s_wired = nm_connection_get_setting_wired (connection);
- setting_mac = s_wired ? nm_setting_wired_get_mac_address (s_wired) : NULL;
-
- parent_iface = nm_setting_vlan_get_parent (s_vlan);
- if (parent_iface) {
- parent = find_device_by_ip_iface (self, parent_iface);
- if (parent)
- return parent;
-
- if (nm_utils_is_uuid (parent_iface)) {
- /* Try as a connection UUID */
- parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (priv->settings, parent_iface);
- if (parent_connection) {
- /* Check if the parent connection is activated on some device already */
- for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
- NMActRequest *req;
- NMConnection *candidate;
-
- req = nm_device_get_act_request (NM_DEVICE (iter->data));
- if (req) {
- candidate = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (req));
- if (candidate == parent_connection)
- return NM_DEVICE (iter->data);
- }
- }
+ /* Try as an interface name */
+ parent = find_device_by_ip_iface (self, parent_name);
+ if (parent)
+ return parent;
- /* Check the hardware address of the parent connection */
- return get_device_from_hwaddr (self, setting_mac);
- }
- return NULL;
- }
- }
+ /* Maybe a hardware address */
+ parent = find_device_by_hw_addr (self, parent_name);
+ if (parent)
+ return parent;
- /* Try the hardware address from the VLAN connection's hardware setting */
- return get_device_from_hwaddr (self, setting_mac);
-}
+ /* Maybe a connection UUID */
+ parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (priv->settings, parent_name);
+ if (!parent_connection)
+ return NULL;
-static NMDevice *
-find_infiniband_parent (NMManager *self,
- NMConnection *connection)
-{
- NMSettingInfiniband *s_infiniband;
- const char *parent_iface;
- NMDevice *parent = NULL;
- const char *setting_mac;
+ /* Check if the parent connection is currently activated or is comaptible
+ * with some known device.
+ */
+ for (iter = priv->devices; iter; iter = iter->next) {
+ NMDevice *candidate = iter->data;
- s_infiniband = nm_connection_get_setting_infiniband (connection);
- g_return_val_if_fail (s_infiniband != NULL, NULL);
+ if (nm_device_get_connection (candidate) == parent_connection)
+ return candidate;
- parent_iface = nm_setting_infiniband_get_parent (s_infiniband);
- if (parent_iface) {
- parent = find_device_by_ip_iface (self, parent_iface);
- if (parent)
- return parent;
+ if ( !first_compatible
+ && nm_device_check_connection_compatible (candidate, parent_connection))
+ first_compatible = candidate;
}
- setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband);
- return get_device_from_hwaddr (self, setting_mac);
+ return first_compatible;
}
/**
@@ -944,86 +927,69 @@ find_infiniband_parent (NMManager *self,
* @self: the #NMManager
* @connection: the #NMConnection representing a virtual interface
* @out_parent: on success, the parent device if any
+ * @error: an error if determining the virtual interface name failed
*
* Given @connection, returns the interface name that the connection
- * would represent. If the interface name is not given by the connection,
- * this may require constructing it based on information in the connection
- * and existing network interfaces.
+ * would represent if it is a virtual connection. %NULL is returned and
+ * @error is set if the connection is not virtual, or if the name could
+ * not be determined.
*
* Returns: the expected interface name (caller takes ownership), or %NULL
*/
static char *
get_virtual_iface_name (NMManager *self,
NMConnection *connection,
- NMDevice **out_parent)
+ NMDevice **out_parent,
+ GError **error)
{
+ NMDeviceFactory *factory;
+ char *iface = NULL;
NMDevice *parent = NULL;
- const char *ifname;
if (out_parent)
*out_parent = NULL;
- if (!nm_connection_is_virtual (connection))
+ if (!nm_connection_is_virtual (connection)) {
+ g_set_error (error,
+ NM_MANAGER_ERROR,
+ NM_MANAGER_ERROR_FAILED,
+ "NetworkManager plugin for '%s' unavailable",
+ nm_connection_get_connection_type (connection));
return NULL;
-
- ifname = nm_connection_get_interface_name (connection);
-
- if (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) {
- NMSettingVlan *s_vlan;
- char *vname;
-
- s_vlan = nm_connection_get_setting_vlan (connection);
- g_return_val_if_fail (s_vlan != NULL, NULL);
-
- parent = find_vlan_parent (self, connection);
- if (!parent)
- return NULL;
-
- if (!nm_device_supports_vlans (parent)) {
- nm_log_warn (LOGD_DEVICE, "(%s): No support for VLANs on interface %s of type %s",
- ifname ? ifname : nm_connection_get_id (connection),
- nm_device_get_ip_iface (parent),
- nm_device_get_type_desc (parent));
- return NULL;
- }
-
- /* If the connection doesn't specify the interface name for the VLAN
- * device, we create one for it using the VLAN ID and the parent
- * interface's name.
- */
- if (ifname)
- vname = g_strdup (ifname);
- else {
- vname = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent),
- nm_setting_vlan_get_id (s_vlan));
- }
- if (out_parent)
- *out_parent = parent;
- return vname;
}
- if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) {
- NMSettingInfiniband *s_infiniband;
-
- parent = find_infiniband_parent (self, connection);
- if (!parent)
- return NULL;
+ factory = nm_device_factory_manager_find_factory_for_connection (connection);
+ if (!factory) {
+ nm_log_warn (LOGD_DEVICE, "(%s) NetworkManager plugin for '%s' unavailable",
+ nm_connection_get_id (connection),
+ nm_connection_get_connection_type (connection));
+ g_set_error (error,
+ NM_MANAGER_ERROR,
+ NM_MANAGER_ERROR_FAILED,
+ "NetworkManager plugin for '%s' unavailable",
+ nm_connection_get_connection_type (connection));
+ return NULL;
+ }
- s_infiniband = nm_connection_get_setting_infiniband (connection);
- if (out_parent)
- *out_parent = parent;
- return g_strdup (nm_setting_infiniband_get_virtual_interface_name (s_infiniband));
+ parent = find_parent_device_for_connection (self, connection);
+ iface = nm_device_factory_get_virtual_iface_name (factory,
+ connection,
+ parent ? nm_device_get_ip_iface (parent) : NULL);
+ if (!iface) {
+ nm_log_warn (LOGD_DEVICE, "(%s) failed to determine virtual interface name",
+ nm_connection_get_id (connection));
+ g_set_error_literal (error,
+ NM_MANAGER_ERROR,
+ NM_MANAGER_ERROR_UNKNOWN_DEVICE,
+ "failed to determine virtual interface name");
+ return NULL;
}
- /* For any other virtual connection, NMSettingConnection:interface-name is
- * the virtual device name.
- */
- g_return_val_if_fail (ifname != NULL, NULL);
- return g_strdup (ifname);
+ if (out_parent)
+ *out_parent = parent;
+ return iface;
}
-/***************************/
-
/**
* system_create_virtual_device:
* @self: the #NMManager
@@ -1039,7 +1005,7 @@ static NMDevice *
system_create_virtual_device (NMManager *self, NMConnection *connection, GError **error)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
- GError *local_err = NULL;
+ NMDeviceFactory *factory;
GSList *iter;
char *iface = NULL;
NMDevice *device = NULL, *parent = NULL;
@@ -1049,16 +1015,9 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- iface = get_virtual_iface_name (self, connection, &parent);
- if (!iface) {
- nm_log_dbg (LOGD_DEVICE, "(%s) failed to determine virtual interface name",
- nm_connection_get_id (connection));
- g_set_error_literal (error,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "failed to determine virtual interface name");
+ iface = get_virtual_iface_name (self, connection, &parent, error);
+ if (!iface)
return NULL;
- }
/* Make sure we didn't create a device for this connection already */
for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
@@ -1076,32 +1035,25 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
}
}
- /* Block notification of link added since we're creating the device
- * explicitly here, otherwise adding the platform/kernel device would
- * create it before this function can do the rest of the setup.
- */
- priv->ignore_link_added_cb++;
-
- nm_owned = !nm_platform_link_exists (iface);
-
- for (iter = priv->factories; iter; iter = iter->next) {
- device = nm_device_factory_create_virtual_device_for_connection (NM_DEVICE_FACTORY (iter->data),
- connection,
- parent,
- &local_err);
- if (device || local_err) {
- if (device)
- g_assert_no_error (local_err);
- else {
- nm_log_err (LOGD_DEVICE, "(%s) failed to create virtual device: %s",
- nm_connection_get_id (connection),
- local_err ? local_err->message : "(unknown error)");
- g_propagate_error (error, local_err);
- }
- break;
- }
+ factory = nm_device_factory_manager_find_factory_for_connection (connection);
+ if (!factory) {
+ nm_log_err (LOGD_DEVICE, "(%s:%s) NetworkManager plugin for '%s' unavailable",
+ nm_connection_get_id (connection), iface,
+ nm_connection_get_connection_type (connection));
+ g_set_error (error,
+ NM_MANAGER_ERROR,
+ NM_MANAGER_ERROR_FAILED,
+ "NetworkManager plugin for '%s' unavailable",
+ nm_connection_get_connection_type (connection));
+ goto out;
}
+ nm_owned = !nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
+
+ device = nm_device_factory_create_virtual_device_for_connection (factory,
+ connection,
+ parent,
+ error);
if (device) {
if (nm_owned)
nm_device_set_nm_owned (device);
@@ -1112,20 +1064,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
add_device (self, device, !nm_owned);
g_object_unref (device);
- } else {
- if (error && !*error)
- nm_log_err (LOGD_DEVICE, "(%s:%s) NetworkManager plugin for '%s' unavailable",
- nm_connection_get_id (connection), iface,
- nm_connection_get_connection_type (connection));
- g_set_error (error,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "NetworkManager plugin for '%s' unavailable",
- nm_connection_get_connection_type (connection));
}
- priv->ignore_link_added_cb--;
-
out:
g_free (iface);
return device;
@@ -1565,13 +1505,13 @@ get_existing_connection (NMManager *manager, NMDevice *device, gboolean *out_gen
nm_device_capture_initial_config (device);
if (ifindex) {
- int master_ifindex = nm_platform_link_get_master (ifindex);
+ int master_ifindex = nm_platform_link_get_master (NM_PLATFORM_GET, ifindex);
if (master_ifindex) {
master = nm_manager_get_device_by_ifindex (manager, master_ifindex);
if (!master) {
nm_log_dbg (LOGD_DEVICE, "(%s): cannot generate connection for slave before its master (%s/%d)",
- nm_device_get_iface (device), nm_platform_link_get_name (master_ifindex), master_ifindex);
+ nm_device_get_iface (device), nm_platform_link_get_name (NM_PLATFORM_GET, master_ifindex), master_ifindex);
return NULL;
}
if (!nm_device_get_act_request (master)) {
@@ -1694,10 +1634,7 @@ recheck_assume_connection (NMDevice *device, gpointer user_data)
if (manager_sleeping (self))
return FALSE;
- if (nm_device_get_unmanaged_flag (device, NM_UNMANAGED_USER) ||
- nm_device_get_unmanaged_flag (device, NM_UNMANAGED_INTERNAL) ||
- nm_device_get_unmanaged_flag (device, NM_UNMANAGED_EXTERNAL_DOWN) ||
- nm_device_get_unmanaged_flag (device, NM_UNMANAGED_PARENT))
+ if (nm_device_get_unmanaged_flag (device, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT))
return FALSE;
state = nm_device_get_state (device);
@@ -1768,6 +1705,18 @@ device_ip_iface_changed (NMDevice *device,
}
}
+static gboolean
+notify_component_added (NMManager *self, GObject *component)
+{
+ GSList *iter;
+
+ for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) {
+ if (nm_device_notify_component_added (NM_DEVICE (iter->data), component))
+ return TRUE;
+ }
+ return FALSE;
+}
+
/**
* add_device:
* @self: the #NMManager
@@ -1788,9 +1737,13 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
RfKillType rtype;
GSList *iter, *remove = NULL;
gboolean connection_assumed = FALSE;
+ int ifindex;
/* No duplicates */
- if (nm_manager_get_device_by_udi (self, nm_device_get_udi (device)))
+ ifindex = nm_device_get_ifindex (device);
+ if (ifindex > 0 && nm_manager_get_device_by_ifindex (self, ifindex))
+ return;
+ if (find_device_by_iface (self, nm_device_get_iface (device)))
return;
/* Remove existing devices owned by the new device; eg remove ethernet
@@ -1852,8 +1805,12 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
driver = nm_device_get_driver (device);
if (!driver)
driver = "unknown";
- nm_log_info (LOGD_HW, "(%s): new %s device (driver: '%s' ifindex: %d)",
- iface, type_desc, driver, nm_device_get_ifindex (device));
+ nm_log_info (LOGD_HW, "(%s): new %s device (carrier: %s, driver: '%s', ifindex: %d)",
+ iface, type_desc,
+ nm_device_has_capability (device, NM_DEVICE_CAP_CARRIER_DETECT)
+ ? (nm_device_has_carrier (device) ? "ON" : "OFF")
+ : "UNKNOWN",
+ driver, nm_device_get_ifindex (device));
unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
user_unmanaged = nm_device_spec_match_list (device, unmanaged_specs);
@@ -1881,27 +1838,14 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES);
+ notify_component_added (self, G_OBJECT (device));
+
/* New devices might be master interfaces for virtual interfaces; so we may
* need to create new virtual interfaces now.
*/
system_create_virtual_devices (self);
}
-static NMDevice *
-find_device_by_ip_iface (NMManager *self, const gchar *iface)
-{
- NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
- GSList *iter;
-
- for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
- NMDevice *candidate = iter->data;
-
- if (g_strcmp0 (nm_device_get_ip_iface (candidate), iface) == 0)
- return candidate;
- }
- return NULL;
-}
-
/*******************************************************************/
static void
@@ -1917,134 +1861,13 @@ factory_component_added_cb (NMDeviceFactory *factory,
GObject *component,
gpointer user_data)
{
- NMManager *self = NM_MANAGER (user_data);
- GSList *iter;
-
- for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) {
- if (nm_device_notify_component_added (NM_DEVICE (iter->data), component))
- return TRUE;
- }
- return FALSE;
-}
-
-#define PLUGIN_PREFIX "libnm-device-plugin-"
-#define PLUGIN_PATH_TAG "NMManager-plugin-path"
-
-struct read_device_factory_paths_data {
- char *path;
- struct stat st;
-};
-
-static gint
-read_device_factory_paths_sort_fcn (gconstpointer a, gconstpointer b)
-{
- const struct read_device_factory_paths_data *da = a;
- const struct read_device_factory_paths_data *db = b;
- time_t ta, tb;
-
- ta = MAX (da->st.st_mtime, da->st.st_ctime);
- tb = MAX (db->st.st_mtime, db->st.st_ctime);
-
- if (ta < tb)
- return 1;
- if (ta > tb)
- return -1;
- return 0;
+ return notify_component_added (NM_MANAGER (user_data), component);
}
-static char**
-read_device_factory_paths (void)
-{
- GDir *dir;
- GError *error = NULL;
- const char *item;
- GArray *paths;
- char **result;
- guint i;
-
- dir = g_dir_open (NMPLUGINDIR, 0, &error);
- if (!dir) {
- nm_log_warn (LOGD_HW, "device plugin: failed to open directory %s: %s",
- NMPLUGINDIR,
- (error && error->message) ? error->message : "(unknown)");
- g_clear_error (&error);
- return NULL;
- }
-
- paths = g_array_new (FALSE, FALSE, sizeof (struct read_device_factory_paths_data));
-
- while ((item = g_dir_read_name (dir))) {
- int errsv;
- struct read_device_factory_paths_data data;
-
- if (!g_str_has_prefix (item, PLUGIN_PREFIX))
- continue;
- if (g_str_has_suffix (item, ".la"))
- continue;
-
- data.path = g_build_filename (NMPLUGINDIR, item, NULL);
-
- if (stat (data.path, &data.st) != 0) {
- errsv = errno;
- nm_log_warn (LOGD_HW, "device plugin: skip invalid file %s (error during stat: %s)", data.path, strerror (errsv));
- goto NEXT;
- }
- if (!S_ISREG (data.st.st_mode))
- goto NEXT;
- if (data.st.st_uid != 0) {
- nm_log_warn (LOGD_HW, "device plugin: skip invalid file %s (file must be owned by root)", data.path);
- goto NEXT;
- }
- if (data.st.st_mode & (S_IWGRP | S_IWOTH | S_ISUID)) {
- nm_log_warn (LOGD_HW, "device plugin: skip invalid file %s (invalid file permissions)", data.path);
- goto NEXT;
- }
-
- g_array_append_val (paths, data);
- continue;
-NEXT:
- g_free (data.path);
- }
- g_dir_close (dir);
-
- /* sort filenames by modification time. */
- g_array_sort (paths, read_device_factory_paths_sort_fcn);
-
- result = g_new (char *, paths->len + 1);
- for (i = 0; i < paths->len; i++)
- result[i] = g_array_index (paths, struct read_device_factory_paths_data, i).path;
- result[i] = NULL;
-
- g_array_free (paths, TRUE);
- return result;
-}
-
-static gboolean
-_register_device_factory (NMManager *self,
- NMDeviceFactory *factory,
- gboolean duplicate_check,
- const char *path,
- GError **error)
+static void
+_register_device_factory (NMDeviceFactory *factory, gpointer user_data)
{
- NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
- NMDeviceType ftype;
- GSList *iter;
-
- if (duplicate_check) {
- /* Make sure we don't double-register factories */
- ftype = nm_device_factory_get_device_type (factory);
- for (iter = priv->factories; iter; iter = iter->next) {
- if (ftype == nm_device_factory_get_device_type (iter->data)) {
- g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
- "multiple plugins for same type (using '%s' instead of '%s')",
- (char *) g_object_get_data (G_OBJECT (iter->data), PLUGIN_PATH_TAG),
- path);
- return FALSE;
- }
- }
- }
-
- priv->factories = g_slist_append (priv->factories, factory);
+ NMManager *self = NM_MANAGER (user_data);
g_signal_connect (factory,
NM_DEVICE_FACTORY_DEVICE_ADDED,
@@ -2054,80 +1877,6 @@ _register_device_factory (NMManager *self,
NM_DEVICE_FACTORY_COMPONENT_ADDED,
G_CALLBACK (factory_component_added_cb),
self);
- g_object_set_data_full (G_OBJECT (factory), PLUGIN_PATH_TAG,
- g_strdup (path), g_free);
- return TRUE;
-}
-
-static void
-load_device_factories (NMManager *self)
-{
- NMDeviceFactory *factory;
- const GSList *iter;
- GError *error = NULL;
- char **path, **paths;
-
- /* Register internal factories first */
- for (iter = nm_device_factory_get_internal_factory_types (); iter; iter = iter->next) {
- GType ftype = (GType) GPOINTER_TO_SIZE (iter->data);
-
- factory = (NMDeviceFactory *) g_object_new (ftype, NULL);
- g_assert (factory);
- if (_register_device_factory (self, factory, FALSE, "internal", &error)) {
- nm_log_dbg (LOGD_HW, "Loaded device plugin: %s", g_type_name (ftype));
- } else {
- nm_log_warn (LOGD_HW, "Loading device plugin failed: %s", error->message);
- g_object_unref (factory);
- g_clear_error (&error);
- }
- }
-
- paths = read_device_factory_paths ();
- if (!paths)
- return;
-
- for (path = paths; *path; path++) {
- GModule *plugin;
- NMDeviceFactoryCreateFunc create_func;
- const char *item;
-
- item = strrchr (*path, '/');
- g_assert (item);
-
- plugin = g_module_open (*path, G_MODULE_BIND_LOCAL);
-
- if (!plugin) {
- nm_log_warn (LOGD_HW, "(%s): failed to load plugin: %s", item, g_module_error ());
- continue;
- }
-
- if (!g_module_symbol (plugin, "nm_device_factory_create", (gpointer) &create_func)) {
- nm_log_warn (LOGD_HW, "(%s): failed to find device factory creator: %s", item, g_module_error ());
- g_module_close (plugin);
- continue;
- }
-
- factory = create_func (&error);
- if (!factory) {
- nm_log_warn (LOGD_HW, "(%s): failed to initialize device factory: %s",
- item, error ? error->message : "unknown");
- g_clear_error (&error);
- g_module_close (plugin);
- continue;
- }
- g_clear_error (&error);
-
- if (_register_device_factory (self, factory, TRUE, g_module_name (plugin), &error)) {
- nm_log_info (LOGD_HW, "Loaded device plugin: %s", g_module_name (plugin));
- g_module_make_resident (plugin);
- } else {
- nm_log_warn (LOGD_HW, "Loading device plugin failed: %s", error->message);
- g_object_unref (factory);
- g_module_close (plugin);
- g_clear_error (&error);
- }
- }
- g_strfreev (paths);
}
/*******************************************************************/
@@ -2135,63 +1884,43 @@ load_device_factories (NMManager *self)
static void
platform_link_added (NMManager *self,
int ifindex,
- NMPlatformLink *plink,
- NMPlatformReason reason)
+ NMPlatformLink *plink)
{
- NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+ NMDeviceFactory *factory;
NMDevice *device = NULL;
- GSList *iter;
GError *error = NULL;
g_return_if_fail (ifindex > 0);
- if (priv->ignore_link_added_cb > 0)
- return;
-
if (nm_manager_get_device_by_ifindex (self, ifindex))
return;
/* Try registered device factories */
- for (iter = priv->factories; iter; iter = iter->next) {
- NMDeviceFactory *factory = NM_DEVICE_FACTORY (iter->data);
-
- device = nm_device_factory_new_link (factory, plink, &error);
- if (device && NM_IS_DEVICE (device)) {
- g_assert_no_error (error);
- break; /* success! */
- }
+ factory = nm_device_factory_manager_find_factory_for_link_type (plink->type);
+ if (factory) {
+ gboolean ignore = FALSE;
- if (error) {
- nm_log_warn (LOGD_HW, "%s: factory failed to create device: (%d) %s",
- plink->udi,
- error ? error->code : -1,
- error ? error->message : "(unknown)");
- g_clear_error (&error);
+ device = nm_device_factory_new_link (factory, plink, &ignore, &error);
+ if (!device) {
+ if (!ignore) {
+ nm_log_warn (LOGD_HW, "%s: factory failed to create device: %s",
+ plink->name, error->message);
+ g_clear_error (&error);
+ }
return;
}
}
- /* Ignore Bluetooth PAN interfaces; they are handled by their NMDeviceBt
- * parent and don't get a separate interface.
- */
- if (!strncmp (plink->name, "bnep", STRLEN ("bnep")))
- return;
-
if (device == NULL) {
switch (plink->type) {
-
case NM_LINK_TYPE_WWAN_ETHERNET:
- /* WWAN pseudo-ethernet interfaces are handled automatically by
- * their NMDeviceModem and don't get a separate NMDevice object.
- */
- break;
-
+ case NM_LINK_TYPE_BNEP:
case NM_LINK_TYPE_OLPC_MESH:
case NM_LINK_TYPE_TEAM:
case NM_LINK_TYPE_WIFI:
case NM_LINK_TYPE_WIMAX:
nm_log_info (LOGD_HW, "(%s): '%s' plugin not available; creating generic device",
- plink->name, plink->type_name);
+ plink->name, nm_link_type_to_string (plink->type));
/* fall through */
default:
device = nm_device_generic_new (plink);
@@ -2205,30 +1934,76 @@ platform_link_added (NMManager *self,
}
}
+typedef struct {
+ NMManager *self;
+ int ifindex;
+} PlatformLinkCbData;
+
+static gboolean
+_platform_link_cb_idle (PlatformLinkCbData *data)
+{
+ NMManager *self = data->self;
+
+ if (self) {
+ const NMPlatformLink *l;
+
+ l = nm_platform_link_get (NM_PLATFORM_GET, data->ifindex);
+ if (l) {
+ NMPlatformLink pllink;
+
+ pllink = *l; /* make a copy of the link instance */
+ platform_link_added (self, data->ifindex, &pllink);
+ } else {
+ NMDevice *device;
+
+ device = nm_manager_get_device_by_ifindex (self, data->ifindex);
+ if (device)
+ remove_device (self, device, FALSE, TRUE);
+ }
+ g_object_remove_weak_pointer (G_OBJECT (self), (gpointer *) &data->self);
+ }
+ g_slice_free (PlatformLinkCbData, data);
+ return G_SOURCE_REMOVE;
+}
+
static void
platform_link_cb (NMPlatform *platform,
+ NMPObjectType obj_type,
int ifindex,
NMPlatformLink *plink,
NMPlatformSignalChangeType change_type,
NMPlatformReason reason,
gpointer user_data)
{
+ PlatformLinkCbData *data;
+
switch (change_type) {
case NM_PLATFORM_SIGNAL_ADDED:
- platform_link_added (NM_MANAGER (user_data), ifindex, plink, reason);
- break;
- case NM_PLATFORM_SIGNAL_REMOVED: {
- NMManager *self = NM_MANAGER (user_data);
- NMDevice *device;
-
- device = nm_manager_get_device_by_ifindex (self, ifindex);
- if (device)
- remove_device (self, device, FALSE, TRUE);
+ case NM_PLATFORM_SIGNAL_REMOVED:
+ data = g_slice_new (PlatformLinkCbData);
+ data->self = NM_MANAGER (user_data);
+ data->ifindex = ifindex;
+ g_object_add_weak_pointer (G_OBJECT (data->self), (gpointer *) &data->self);
+ g_idle_add ((GSourceFunc) _platform_link_cb_idle, data);
break;
- }
- default:
+ default:
break;
- }
+ }
+}
+
+static void
+platform_query_devices (NMManager *self)
+{
+ GArray *links_array;
+ NMPlatformLink *links;
+ int i;
+
+ links_array = nm_platform_link_get_all (NM_PLATFORM_GET);
+ links = (NMPlatformLink *) links_array->data;
+ for (i = 0; i < links_array->len; i++)
+ platform_link_added (self, links[i].ifindex, &links[i]);
+
+ g_array_unref (links_array);
}
static void
@@ -2248,6 +2023,40 @@ nm_manager_get_devices (NMManager *manager)
return NM_MANAGER_GET_PRIVATE (manager)->devices;
}
+static NMDevice *
+nm_manager_get_connection_device (NMManager *self,
+ NMConnection *connection)
+{
+ NMActiveConnection *ac = find_ac_for_connection (self, connection);
+ if (ac == NULL)
+ return NULL;
+
+ return nm_active_connection_get_device (ac);
+}
+
+static NMDevice *
+nm_manager_get_best_device_for_connection (NMManager *self,
+ NMConnection *connection)
+{
+ const GSList *devices, *iter;
+ NMDevice *act_device = nm_manager_get_connection_device (self, connection);
+
+ if (act_device)
+ return act_device;
+
+ /* Pick the first device that's compatible with the connection. */
+ devices = nm_manager_get_devices (self);
+ for (iter = devices; iter; iter = g_slist_next (iter)) {
+ NMDevice *device = NM_DEVICE (iter->data);
+
+ if (nm_device_check_connection_available (device, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL))
+ return device;
+ }
+
+ /* No luck. :( */
+ return NULL;
+}
+
static gboolean
impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err)
{
@@ -2411,13 +2220,10 @@ find_master (NMManager *self,
NMConnection *candidate = iter->data;
char *vname;
- if (nm_connection_is_virtual (candidate)) {
- vname = get_virtual_iface_name (self, candidate, NULL);
- if ( g_strcmp0 (master, vname) == 0
- && is_compatible_with_slave (candidate, connection))
- master_connection = candidate;
- g_free (vname);
- }
+ vname = get_virtual_iface_name (self, candidate, NULL, NULL);
+ if (g_strcmp0 (master, vname) == 0 && is_compatible_with_slave (candidate, connection))
+ master_connection = candidate;
+ g_free (vname);
}
g_slist_free (connections);
}
@@ -2615,6 +2421,127 @@ ensure_master_active_connection (NMManager *self,
return NULL;
}
+/**
+ * find_slaves:
+ * @manager: #NMManager object
+ * @connection: the master #NMConnection to find slave connections for
+ * @device: the master #NMDevice for the @connection
+ *
+ * Given an #NMConnection, attempts to find its slaves. If @connection is not
+ * master, or has not any slaves, this will return %NULL.
+ *
+ * Returns: list of slave connections for given master @connection, or %NULL
+ **/
+static GSList *
+find_slaves (NMManager *manager,
+ NMConnection *connection,
+ NMDevice *device)
+{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
+ GSList *all_connections, *iter;
+ GSList *slaves = NULL;
+ NMSettingConnection *s_con;
+ const char *master;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ master = nm_setting_connection_get_master (s_con);
+
+ if (master != NULL)
+ return NULL; /* connection is not master */
+
+ /* Search through all connections, not only inactive ones, because
+ * even if a slave was already active, it might be deactivated during
+ * master reactivation.
+ */
+ all_connections = nm_settings_get_connections (priv->settings);
+ for (iter = all_connections; iter; iter = iter->next) {
+ NMConnection *master_connection = NULL;
+ NMDevice *master_device = NULL;
+ NMConnection *candidate = iter->data;
+
+ find_master (manager, candidate, NULL, &master_connection, &master_device, NULL, NULL);
+ if ( (master_connection && master_connection == connection)
+ || (master_device && master_device == device)) {
+ slaves = g_slist_prepend (slaves, candidate);
+ }
+ }
+ g_slist_free (all_connections);
+
+ return g_slist_reverse (slaves);
+}
+
+static gboolean
+should_connect_slaves (NMConnection *connection, NMDevice *device)
+{
+ NMSettingConnection *s_con;
+ NMSettingConnectionAutoconnectSlaves autoconnect_slaves;
+ gs_free char *value = NULL;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+
+ /* Check autoconnect-slaves property */
+ autoconnect_slaves = nm_setting_connection_get_autoconnect_slaves (s_con);
+ if (autoconnect_slaves != NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT)
+ goto out;
+
+ /* Check configuration default for autoconnect-slaves property */
+ value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ "connection.autoconnect-slaves", device);
+ if (value)
+ autoconnect_slaves = _nm_utils_ascii_str_to_int64 (value, 10, 0, 1, -1);
+
+out:
+ if (autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO)
+ return FALSE;
+ if (autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES)
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+autoconnect_slaves (NMManager *manager,
+ NMConnection *master_connection,
+ NMDevice *master_device,
+ NMAuthSubject *subject)
+{
+ GError *local_err = NULL;
+ gboolean ret = FALSE;
+
+ if (should_connect_slaves (master_connection, master_device)) {
+ GSList *slaves, *iter;
+
+ iter = slaves = find_slaves (manager, master_connection, master_device);
+ ret = slaves != NULL;
+
+ while (iter) {
+ NMConnection *slave_connection = iter->data;
+
+ iter = iter->next;
+ nm_log_dbg (LOGD_CORE, "will activate slave connection '%s' (%s) as a dependency for master '%s' (%s)",
+ nm_connection_get_id (slave_connection),
+ nm_connection_get_uuid (slave_connection),
+ nm_connection_get_id (master_connection),
+ nm_connection_get_uuid (master_connection));
+
+ /* Schedule slave activation */
+ nm_manager_activate_connection (manager,
+ slave_connection,
+ NULL,
+ nm_manager_get_best_device_for_connection (manager, slave_connection),
+ subject,
+ &local_err);
+ if (local_err) {
+ nm_log_warn (LOGD_CORE, "Slave connection activation failed: %s", local_err->message);
+ g_error_free (local_err);
+ }
+ }
+ g_slist_free (slaves);
+ }
+ return ret;
+}
+
static gboolean
_internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **error)
{
@@ -2635,7 +2562,7 @@ _internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **er
static gboolean
_internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error)
{
- NMDevice *device, *master_device = NULL;
+ NMDevice *device, *existing, *master_device = NULL;
NMConnection *connection;
NMConnection *master_connection = NULL;
NMActiveConnection *master_ac = NULL;
@@ -2783,11 +2710,19 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
}
nm_active_connection_set_master (active, master_ac);
- nm_log_dbg (LOGD_CORE, "Activation of '%s' depends on active connection %s",
+ nm_log_dbg (LOGD_CORE, "Activation of '%s' depends on active connection %p",
nm_connection_get_id (connection),
- nm_active_connection_get_path (master_ac));
+ master_ac);
}
+ /* Check slaves for master connection and possibly activate them */
+ autoconnect_slaves (self, connection, device, nm_active_connection_get_subject (active));
+
+ /* Disconnect the connection if connected or queued on another device */
+ existing = nm_manager_get_connection_device (self, connection);
+ if (existing)
+ nm_device_steal_connection (existing, connection);
+
/* Export the new ActiveConnection to clients and start it on the device */
nm_active_connection_export (active);
g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
@@ -2825,6 +2760,7 @@ _internal_activate_generic (NMManager *self, NMActiveConnection *active, GError
* is exported, make sure the manager's activating-connection property
* is up-to-date.
*/
+ active_connection_add (self, active);
policy_activating_device_changed (G_OBJECT (priv->policy), NULL, self);
}
@@ -2894,18 +2830,6 @@ _new_active_connection (NMManager *self,
return NULL;
}
- if (existing_ac) {
- NMDevice *existing_device = nm_active_connection_get_device (existing_ac);
-
- if (existing_device != device) {
- g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE,
- "Connection '%s' is already active on %s",
- nm_connection_get_id (connection),
- nm_device_get_iface (existing_device));
- return NULL;
- }
- }
-
/* Normalize the specific object */
if (specific_object && g_strcmp0 (specific_object, "/") == 0)
specific_object = NULL;
@@ -2929,15 +2853,14 @@ _internal_activation_failed (NMManager *self,
NMActiveConnection *active,
const char *error_desc)
{
- nm_log_warn (LOGD_CORE, "Failed to activate '%s': %s",
- nm_connection_get_id (nm_active_connection_get_connection (active)),
- error_desc);
+ nm_log_dbg (LOGD_CORE, "Failed to activate '%s': %s",
+ nm_connection_get_id (nm_active_connection_get_connection (active)),
+ error_desc);
if (nm_active_connection_get_state (active) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING);
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
}
- active_connection_remove (self, active);
}
static void
@@ -2948,8 +2871,11 @@ _internal_activation_auth_done (NMActiveConnection *active,
gpointer user_data2)
{
NMManager *self = user_data1;
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GError *error = NULL;
+ priv->authorizing_connections = g_slist_remove (priv->authorizing_connections, active);
+
if (success) {
if (_internal_activate_generic (self, active, &error)) {
g_object_unref (active);
@@ -2989,8 +2915,10 @@ nm_manager_activate_connection (NMManager *self,
NMAuthSubject *subject,
GError **error)
{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
NMActiveConnection *active;
char *error_desc = NULL;
+ GSList *iter;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
@@ -3010,6 +2938,22 @@ nm_manager_activate_connection (NMManager *self,
return NULL;
}
+ /* Look for a active connection that's equivalent and is already pending authorization
+ * and eventual activation. This is used to de-duplicate concurrent activations which would
+ * otherwise race and cause the device to disconnect and reconnect repeatedly.
+ * In particular, this allows the master and multiple slaves to concurrently auto-activate
+ * while all the slaves would use the same active-connection. */
+ for (iter = priv->authorizing_connections; iter; iter = g_slist_next (iter)) {
+ active = iter->data;
+
+ if ( connection == nm_active_connection_get_connection (active)
+ && g_strcmp0 (nm_active_connection_get_specific_object (active), specific_object) == 0
+ && nm_active_connection_get_device (active) == device
+ && nm_auth_subject_is_internal (nm_active_connection_get_subject (active))
+ && nm_auth_subject_is_internal (subject))
+ return active;
+ }
+
active = _new_active_connection (self,
connection,
specific_object,
@@ -3017,8 +2961,8 @@ nm_manager_activate_connection (NMManager *self,
subject,
error);
if (active) {
+ priv->authorizing_connections = g_slist_prepend (priv->authorizing_connections, active);
nm_active_connection_authorize (active, _internal_activation_auth_done, self, NULL);
- active_connection_add (self, active);
}
return active;
}
@@ -3064,6 +3008,18 @@ validate_activation_request (NMManager *self,
goto error;
}
+ /* Not implemented yet, we want to fail early */
+ if ( nm_connection_get_setting_connection (connection)
+ && nm_connection_get_setting_ip6_config (connection)
+ && !strcmp (nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG),
+ NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
+ g_set_error_literal (error,
+ NM_MANAGER_ERROR,
+ NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE,
+ "Sharing IPv6 connections is not supported yet.");
+ return NULL;
+ }
+
/* Check whether it's a VPN or not */
if ( nm_connection_get_setting_vpn (connection)
|| nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME))
@@ -3083,7 +3039,10 @@ validate_activation_request (NMManager *self,
"Device not found");
goto error;
}
- } else {
+ } else
+ device = nm_manager_get_best_device_for_connection (self, connection);
+
+ if (!device) {
gboolean is_software = nm_connection_is_virtual (connection);
/* VPN and software-device connections don't need a device yet */
@@ -3091,22 +3050,17 @@ validate_activation_request (NMManager *self,
g_set_error_literal (error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_UNKNOWN_DEVICE,
- "This connection requires an existing device.");
+ "No suitable device found for this connection.");
goto error;
}
if (is_software) {
- /* Look for an existing device with the connection's interface name */
char *iface;
- iface = get_virtual_iface_name (self, 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");
+ /* Look for an existing device with the connection's interface name */
+ iface = get_virtual_iface_name (self, connection, NULL, error);
+ if (!iface)
goto error;
- }
device = find_device_by_ip_iface (self, iface);
g_free (iface);
@@ -3252,7 +3206,6 @@ impl_manager_activate_connection (NMManager *self,
goto error;
nm_active_connection_authorize (active, _activation_auth_done, self, context);
- active_connection_add (self, active);
g_clear_object (&subject);
return;
@@ -3330,8 +3283,6 @@ _add_and_activate_auth_done (NMActiveConnection *active,
activation_add_done,
info);
} else {
- active_connection_remove (self, active);
-
g_assert (error_desc);
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
@@ -3438,7 +3389,6 @@ impl_manager_add_and_activate_connection (NMManager *self,
goto error;
nm_active_connection_authorize (active, _add_and_activate_auth_done, self, context);
- active_connection_add (self, active);
g_object_unref (connection);
g_object_unref (subject);
return;
@@ -3616,7 +3566,7 @@ done:
static gboolean
device_is_wake_on_lan (NMDevice *device)
{
- return nm_platform_link_get_wake_on_lan (nm_device_get_ip_ifindex (device));
+ return nm_platform_link_get_wake_on_lan (NM_PLATFORM_GET, nm_device_get_ip_ifindex (device));
}
static void
@@ -4172,11 +4122,16 @@ impl_manager_check_connectivity (NMManager *manager,
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
}
+static void
+start_factory (NMDeviceFactory *factory, gpointer user_data)
+{
+ nm_device_factory_start (factory);
+}
+
void
nm_manager_start (NMManager *self)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
- GSList *iter;
guint i;
/* Set initial radio enabled/disabled state */
@@ -4208,10 +4163,9 @@ nm_manager_start (NMManager *self)
system_hostname_changed_cb (priv->settings, NULL, self);
/* Start device factories */
- for (iter = priv->factories; iter; iter = iter->next)
- nm_device_factory_start (iter->data);
+ nm_device_factory_manager_for_each_factory (start_factory, NULL);
- nm_platform_query_devices ();
+ platform_query_devices (self);
/*
* Connections added before the manager is started do not emit
@@ -4270,12 +4224,9 @@ connectivity_changed (NMConnectivity *connectivity,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
- NMConnectivityState state;
- static const char *connectivity_states[] = { "UNKNOWN", "NONE", "PORTAL", "LIMITED", "FULL" };
- state = nm_connectivity_get_state (connectivity);
nm_log_dbg (LOGD_CORE, "connectivity checking indicates %s",
- connectivity_states[state]);
+ nm_connectivity_state_to_string (nm_connectivity_get_state (connectivity)));
nm_manager_update_state (self);
g_object_notify (G_OBJECT (self), NM_MANAGER_CONNECTIVITY);
@@ -4718,6 +4669,7 @@ nm_manager_new (NMSettings *settings,
NMManagerPrivate *priv;
DBusGConnection *bus;
DBusConnection *dbus_connection;
+ NMConfigData *config_data;
g_assert (settings);
@@ -4749,7 +4701,16 @@ nm_manager_new (NMSettings *settings,
g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_DEVICE,
G_CALLBACK (policy_activating_device_changed), singleton);
- priv->connectivity = nm_connectivity_new ();
+ priv->config = g_object_ref (nm_config_get ());
+ g_signal_connect (G_OBJECT (priv->config),
+ NM_CONFIG_SIGNAL_CONFIG_CHANGED,
+ G_CALLBACK (_config_changed_cb),
+ singleton);
+
+ config_data = nm_config_get_data (priv->config);
+ priv->connectivity = nm_connectivity_new (nm_config_data_get_connectivity_uri (config_data),
+ nm_config_data_get_connectivity_interval (config_data),
+ nm_config_data_get_connectivity_response (config_data));
g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE,
G_CALLBACK (connectivity_changed), singleton);
@@ -4807,7 +4768,7 @@ nm_manager_new (NMSettings *settings,
rfkill_change (priv->radio_states[RFKILL_TYPE_WLAN].desc, RFKILL_TYPE_WLAN, initial_wifi_enabled);
rfkill_change (priv->radio_states[RFKILL_TYPE_WWAN].desc, RFKILL_TYPE_WWAN, initial_wwan_enabled);
- load_device_factories (singleton);
+ nm_device_factory_manager_load_factories (_register_device_factory, singleton);
return singleton;
}
@@ -5042,13 +5003,18 @@ set_property (GObject *object, guint prop_id,
}
static void
+_deinit_device_factory (NMDeviceFactory *factory, gpointer user_data)
+{
+ g_signal_handlers_disconnect_matched (factory, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NM_MANAGER (user_data));
+}
+
+static void
dispose (GObject *object)
{
NMManager *manager = NM_MANAGER (object);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
DBusGConnection *bus;
DBusConnection *dbus_connection;
- GSList *iter;
g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref);
priv->auth_chains = NULL;
@@ -5070,7 +5036,14 @@ dispose (GObject *object)
g_clear_object (&priv->primary_connection);
g_clear_object (&priv->activating_connection);
- g_clear_object (&priv->connectivity);
+ if (priv->config) {
+ g_signal_handlers_disconnect_by_func (priv->config, _config_changed_cb, manager);
+ g_clear_object (&priv->config);
+ }
+ if (priv->connectivity) {
+ g_signal_handlers_disconnect_by_func (priv->connectivity, connectivity_changed, manager);
+ g_clear_object (&priv->connectivity);
+ }
g_free (priv->hostname);
@@ -5113,14 +5086,8 @@ dispose (GObject *object)
g_clear_object (&priv->fw_monitor);
}
- for (iter = priv->factories; iter; iter = iter->next) {
- NMDeviceFactory *factory = iter->data;
-
- g_signal_handlers_disconnect_matched (factory, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager);
- g_object_unref (factory);
- }
- g_clear_pointer (&priv->factories, g_slist_free);
-
+ nm_device_factory_manager_for_each_factory (_deinit_device_factory, manager);
+
if (priv->timestamp_update_id) {
g_source_remove (priv->timestamp_update_id);
priv->timestamp_update_id = 0;