summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/devices/adsl/nm-atm-manager.c11
-rw-r--r--src/devices/bluetooth/nm-bluez-manager.c11
-rw-r--r--src/devices/nm-device-bond.c39
-rw-r--r--src/devices/nm-device-bridge.c39
-rw-r--r--src/devices/nm-device-ethernet.c19
-rw-r--r--src/devices/nm-device-factory.c402
-rw-r--r--src/devices/nm-device-factory.h83
-rw-r--r--src/devices/nm-device-gre.c18
-rw-r--r--src/devices/nm-device-infiniband.c35
-rw-r--r--src/devices/nm-device-macvlan.c18
-rw-r--r--src/devices/nm-device-tun.c11
-rw-r--r--src/devices/nm-device-veth.c18
-rw-r--r--src/devices/nm-device-vlan.c50
-rw-r--r--src/devices/nm-device-vxlan.c18
-rw-r--r--src/devices/team/nm-device-team.c18
-rw-r--r--src/devices/team/nm-team-factory.c19
-rw-r--r--src/devices/wifi/nm-wifi-factory.c15
-rw-r--r--src/devices/wimax/nm-wimax-factory.c12
-rw-r--r--src/devices/wwan/nm-wwan-factory.c13
-rw-r--r--src/nm-manager.c309
20 files changed, 658 insertions, 500 deletions
diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c
index 6f34c02bbd..0830f85d15 100644
--- a/src/devices/adsl/nm-atm-manager.c
+++ b/src/devices/adsl/nm-atm-manager.c
@@ -25,6 +25,7 @@
#include <gmodule.h>
#include "nm-atm-manager.h"
+#include "nm-setting-adsl.h"
#include "nm-device-adsl.h"
#include "nm-device-factory.h"
#include "nm-logging.h"
@@ -203,11 +204,9 @@ handle_uevent (GUdevClient *client,
adsl_remove (self, device);
}
-static NMDeviceType
-get_device_type (NMDeviceFactory *factory)
-{
- return NM_DEVICE_TYPE_ADSL;
-}
+NM_DEVICE_FACTORY_DECLARE_TYPES (
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_ADSL_SETTING_NAME)
+)
/*********************************************************************/
@@ -224,7 +223,7 @@ nm_atm_manager_init (NMAtmManager *self)
static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
- factory_iface->get_device_type = get_device_type;
+ factory_iface->get_supported_types = get_supported_types;
factory_iface->start = start;
}
diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c
index e176a4b462..d2e5e96e08 100644
--- a/src/devices/bluetooth/nm-bluez-manager.c
+++ b/src/devices/bluetooth/nm-bluez-manager.c
@@ -29,6 +29,7 @@
#include "nm-logging.h"
#include "nm-bluez-manager.h"
#include "nm-device-factory.h"
+#include "nm-setting-bluetooth.h"
#include "nm-bluez4-manager.h"
#include "nm-bluez5-manager.h"
#include "nm-bluez-device.h"
@@ -368,11 +369,9 @@ start (NMDeviceFactory *factory)
check_bluez_and_try_setup (NM_BLUEZ_MANAGER (factory));
}
-static NMDeviceType
-get_device_type (NMDeviceFactory *factory)
-{
- return NM_DEVICE_TYPE_BT;
-}
+NM_DEVICE_FACTORY_DECLARE_TYPES (
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BLUETOOTH_SETTING_NAME)
+)
/*********************************************************************/
@@ -408,7 +407,7 @@ nm_bluez_manager_init (NMBluezManager *self)
static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
- factory_iface->get_device_type = get_device_type;
+ factory_iface->get_supported_types = get_supported_types;
factory_iface->start = start;
}
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 0821fe4253..14ccedfb78 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -557,16 +557,13 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_BOND) {
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_DRIVER, "bonding",
- NM_DEVICE_TYPE_DESC, "Bond",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
- NM_DEVICE_IS_MASTER, TRUE,
- NULL);
- }
- return NULL;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
+ NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_DRIVER, "bonding",
+ NM_DEVICE_TYPE_DESC, "Bond",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
+ NM_DEVICE_IS_MASTER, TRUE,
+ NULL);
}
static NMDevice *
@@ -575,19 +572,17 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NMDevice *parent,
GError **error)
{
- const char *iface;
+ const char *iface = nm_connection_get_interface_name (connection);
- if (!nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
- return NULL;
-
- iface = nm_connection_get_interface_name (connection);
- g_return_val_if_fail (iface != NULL, NULL);
+ g_assert (iface);
if ( !nm_platform_bond_add (NM_PLATFORM_GET, iface)
- && nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
- nm_log_warn (LOGD_DEVICE | LOGD_BOND, "(%s): failed to create bonding master interface for '%s': %s",
- iface, nm_connection_get_id (connection),
- nm_platform_get_error_msg (NM_PLATFORM_GET));
+ && nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create bond interface '%s' for '%s': %s",
+ iface,
+ nm_connection_get_id (connection),
+ nm_platform_get_error_msg (NM_PLATFORM_GET));
return NULL;
}
@@ -600,7 +595,9 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL(BOND, Bond, bond,
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (BOND, Bond, bond,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_BOND)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BOND_SETTING_NAME),
factory_iface->new_link = new_link;
factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
)
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index 30081e1e23..f3c3eea5e0 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -480,16 +480,13 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_BRIDGE) {
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_DRIVER, "bridge",
- NM_DEVICE_TYPE_DESC, "Bridge",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
- NM_DEVICE_IS_MASTER, TRUE,
- NULL);
- }
- return NULL;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
+ NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_DRIVER, "bridge",
+ NM_DEVICE_TYPE_DESC, "Bridge",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
+ NM_DEVICE_IS_MASTER, TRUE,
+ NULL);
}
static NMDevice *
@@ -498,21 +495,15 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NMDevice *parent,
GError **error)
{
- const char *iface;
+ const char *iface = nm_connection_get_interface_name (connection);
NMSettingBridge *s_bridge;
const char *mac_address_str;
guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX];
- if (!nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
- return NULL;
-
- g_return_val_if_fail (connection != NULL, NULL);
-
- iface = nm_connection_get_interface_name (connection);
- g_return_val_if_fail (iface != NULL, NULL);
+ g_assert (iface);
s_bridge = nm_connection_get_setting_bridge (connection);
- g_return_val_if_fail (s_bridge, NULL);
+ g_assert (s_bridge);
mac_address_str = nm_setting_bridge_get_mac_address (s_bridge);
if (mac_address_str) {
@@ -525,8 +516,10 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
mac_address_str ? mac_address : NULL,
mac_address_str ? ETH_ALEN : 0)
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
- nm_log_warn (LOGD_DEVICE | LOGD_BRIDGE, "(%s): failed to create bridge master interface for '%s': %s",
- iface, nm_connection_get_id (connection),
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create bridge interface '%s' for '%s': %s",
+ iface,
+ nm_connection_get_id (connection),
nm_platform_get_error_msg (NM_PLATFORM_GET));
return NULL;
}
@@ -540,7 +533,9 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL(BRIDGE, Bridge, bridge,
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (BRIDGE, Bridge, bridge,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_BRIDGE)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BRIDGE_SETTING_NAME),
factory_iface->new_link = new_link;
factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
)
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index 041eb278e7..dd8de2e590 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -1757,17 +1757,16 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_ETHERNET) {
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_TYPE_DESC, "Ethernet",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
- NULL);
- }
- return NULL;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET,
+ NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_TYPE_DESC, "Ethernet",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
+ NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL(ETHERNET, Ethernet, ethernet, \
- factory_iface->new_link = new_link; \
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (ETHERNET, Ethernet, ethernet,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_ETHERNET)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_PPPOE_SETTING_NAME),
+ factory_iface->new_link = new_link;
)
diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c
index abfb8d4a67..9957efdc33 100644
--- a/src/devices/nm-device-factory.c
+++ b/src/devices/nm-device-factory.c
@@ -19,8 +19,19 @@
*/
#include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+
+#include <gmodule.h>
#include "nm-device-factory.h"
+#include "nm-logging.h"
+#include "nm-platform.h"
+
+const NMLinkType _nm_device_factory_no_default_links[] = { NM_LINK_TYPE_NONE };
+const char *_nm_device_factory_no_default_settings[] = { NULL };
enum {
DEVICE_ADDED,
@@ -29,21 +40,6 @@ enum {
};
static guint signals[LAST_SIGNAL] = { 0 };
-static GSList *internal_types = NULL;
-
-void
-_nm_device_factory_internal_register_type (GType factory_type)
-{
- g_return_if_fail (g_slist_find (internal_types, GUINT_TO_POINTER (factory_type)) == NULL);
- internal_types = g_slist_prepend (internal_types, GUINT_TO_POINTER (factory_type));
-}
-
-const GSList *
-nm_device_factory_get_internal_factory_types (void)
-{
- return internal_types;
-}
-
gboolean
nm_device_factory_emit_component_added (NMDeviceFactory *factory, GObject *component)
{
@@ -108,12 +104,24 @@ nm_device_factory_get_type (void)
return device_factory_type;
}
-NMDeviceType
-nm_device_factory_get_device_type (NMDeviceFactory *factory)
+void
+nm_device_factory_get_supported_types (NMDeviceFactory *factory,
+ const NMLinkType **out_link_types,
+ const char ***out_setting_types)
{
- g_return_val_if_fail (factory != NULL, NM_DEVICE_TYPE_UNKNOWN);
+ const NMLinkType *link_types_fallback;
+ const char **setting_types_fallback;
+
+ g_return_if_fail (factory != NULL);
+
+ if (!out_link_types)
+ out_link_types = &link_types_fallback;
+ if (!out_setting_types)
+ out_setting_types = &setting_types_fallback;
- return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_device_type (factory);
+ NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_supported_types (factory,
+ out_link_types,
+ out_setting_types);
}
void
@@ -130,12 +138,38 @@ nm_device_factory_new_link (NMDeviceFactory *factory,
NMPlatformLink *plink,
GError **error)
{
+ NMDeviceFactory *interface;
+ const NMLinkType *link_types = NULL;
+ const char **setting_types = NULL;
+ int i;
+
g_return_val_if_fail (factory != NULL, NULL);
g_return_val_if_fail (plink != NULL, NULL);
- if (NM_DEVICE_FACTORY_GET_INTERFACE (factory)->new_link)
- return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->new_link (factory, plink, error);
- return NULL;
+ /* Ensure the factory can create interfaces for this connection */
+ nm_device_factory_get_supported_types (factory, &link_types, &setting_types);
+ for (i = 0; link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
+ if (plink->type == link_types[i])
+ break;
+ }
+
+ if (link_types[i] == NM_LINK_TYPE_UNKNOWN) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Device factory %s does not support link type %s (%d)",
+ G_OBJECT_TYPE_NAME (factory),
+ plink->kind, plink->type);
+ return NULL;
+ }
+
+ interface = NM_DEVICE_FACTORY_GET_INTERFACE (factory);
+ if (!interface->new_link) {
+ g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
+ "Device factory %s cannot manage new devices",
+ G_OBJECT_TYPE_NAME (factory));
+ return NULL;
+ }
+
+ return interface->new_link (factory, plink, error);
}
NMDevice *
@@ -145,14 +179,334 @@ nm_device_factory_create_virtual_device_for_connection (NMDeviceFactory *factory
GError **error)
{
NMDeviceFactory *interface;
+ const char **setting_types = NULL;
+ gboolean found = FALSE;
+ int i;
g_return_val_if_fail (factory, NULL);
g_return_val_if_fail (connection, NULL);
g_return_val_if_fail (!error || !*error, NULL);
+ /* Ensure the factory can create interfaces for this connection */
+ nm_device_factory_get_supported_types (factory, NULL, &setting_types);
+ for (i = 0; setting_types && setting_types[i]; i++) {
+ if (nm_connection_is_type (connection, setting_types[i])) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
+ "Device factory %s does not support connection type %s",
+ G_OBJECT_TYPE_NAME (factory),
+ nm_connection_get_connection_type (connection));
+ return NULL;
+ }
+
interface = NM_DEVICE_FACTORY_GET_INTERFACE (factory);
- if (interface->create_virtual_device_for_connection)
- return interface->create_virtual_device_for_connection (factory, connection, parent, error);
+ if (!interface->create_virtual_device_for_connection) {
+ g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
+ "Device factory %s cannot create virtual devices",
+ G_OBJECT_TYPE_NAME (factory));
+ return NULL;
+ }
+
+ return interface->create_virtual_device_for_connection (factory, connection, parent, error);
+}
+
+/*******************************************************************/
+
+static GSList *internal_types = NULL;
+static GHashTable *factories_by_link = NULL;
+static GHashTable *factories_by_setting = NULL;
+
+void
+_nm_device_factory_internal_register_type (GType factory_type)
+{
+ g_return_if_fail (g_slist_find (internal_types, GUINT_TO_POINTER (factory_type)) == NULL);
+ internal_types = g_slist_prepend (internal_types, GUINT_TO_POINTER (factory_type));
+}
+
+static void __attribute__((destructor))
+_cleanup (void)
+{
+ g_clear_pointer (&internal_types, g_slist_free);
+ g_clear_pointer (&factories_by_link, g_hash_table_unref);
+ g_clear_pointer (&factories_by_setting, g_hash_table_unref);
+}
+
+static NMDeviceFactory *
+find_factory (const NMLinkType *needle_link_types,
+ const char **needle_setting_types)
+{
+ NMDeviceFactory *found;
+ guint i;
+
+ g_return_val_if_fail (factories_by_link, NULL);
+ g_return_val_if_fail (factories_by_setting, NULL);
+
+ /* NMLinkType search */
+ for (i = 0; needle_link_types && needle_link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
+ found = g_hash_table_lookup (factories_by_link, GUINT_TO_POINTER (needle_link_types[i]));
+ if (found)
+ return found;
+ }
+
+ /* NMSetting name search */
+ for (i = 0; needle_setting_types && needle_setting_types[i]; i++) {
+ found = g_hash_table_lookup (factories_by_setting, needle_setting_types[i]);
+ if (found)
+ return found;
+ }
+
return NULL;
}
+NMDeviceFactory *
+nm_device_factory_manager_find_factory_for_link_type (NMLinkType link_type)
+{
+ const NMLinkType ltypes[2] = { link_type, NM_LINK_TYPE_NONE };
+
+ g_assert (ltypes[0] > NM_LINK_TYPE_UNKNOWN);
+ return find_factory (ltypes, NULL);
+}
+
+NMDeviceFactory *
+nm_device_factory_manager_find_factory_for_connection (NMConnection *connection)
+{
+ const char *stypes[2] = { nm_connection_get_connection_type (connection), NULL };
+
+ g_assert (stypes[0]);
+ return find_factory (NULL, stypes);
+}
+
+void
+nm_device_factory_manager_for_each_factory (NMDeviceFactoryManagerFactoryFunc callback,
+ gpointer user_data)
+{
+ GHashTableIter iter;
+ NMDeviceFactory *factory;
+ GSList *list_iter, *list = NULL;
+
+ g_return_if_fail (factories_by_link);
+ g_return_if_fail (factories_by_setting);
+
+ g_hash_table_iter_init (&iter, factories_by_link);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &factory)) {
+ if (!g_slist_find (list, factory))
+ list = g_slist_prepend (list, factory);
+ }
+
+ g_hash_table_iter_init (&iter, factories_by_setting);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &factory)) {
+ if (!g_slist_find (list, factory))
+ list = g_slist_prepend (list, factory);
+ }
+
+ for (list_iter = list; list_iter; list_iter = list_iter->next)
+ callback (list_iter->data, user_data);
+
+ g_slist_free (list);
+}
+
+#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;
+}
+
+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
+_add_factory (NMDeviceFactory *factory,
+ gboolean check_duplicates,
+ const char *path,
+ NMDeviceFactoryManagerFactoryFunc callback,
+ gpointer user_data)
+{
+ NMDeviceFactory *found = NULL;
+ const NMLinkType *link_types = NULL;
+ const char **setting_types = NULL;
+ int i;
+
+ g_return_val_if_fail (factories_by_link, FALSE);
+ g_return_val_if_fail (factories_by_setting, FALSE);
+
+ nm_device_factory_get_supported_types (factory, &link_types, &setting_types);
+ if (check_duplicates) {
+ found = find_factory (link_types, setting_types);
+ if (found) {
+ nm_log_warn (LOGD_HW, "Loading device plugin failed: multiple plugins "
+ "for same type (using '%s' instead of '%s')",
+ (char *) g_object_get_data (G_OBJECT (found), PLUGIN_PATH_TAG),
+ path);
+ return FALSE;
+ }
+ }
+
+ g_object_set_data_full (G_OBJECT (factory), PLUGIN_PATH_TAG, g_strdup (path), g_free);
+ for (i = 0; link_types && link_types[i] > NM_LINK_TYPE_UNKNOWN; i++)
+ g_hash_table_insert (factories_by_link, GUINT_TO_POINTER (link_types[i]), g_object_ref (factory));
+ for (i = 0; setting_types && setting_types[i]; i++)
+ g_hash_table_insert (factories_by_setting, (char *) setting_types[i], g_object_ref (factory));
+
+ callback (factory, user_data);
+
+ nm_log_info (LOGD_HW, "Loaded device plugin: %s (%s)", G_OBJECT_TYPE_NAME (factory), path);
+ return TRUE;
+}
+
+void
+nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc callback,
+ gpointer user_data)
+{
+ NMDeviceFactory *factory;
+ const GSList *iter;
+ GError *error = NULL;
+ char **path, **paths;
+
+ g_return_if_fail (factories_by_link == NULL);
+ g_return_if_fail (factories_by_setting == NULL);
+
+ factories_by_link = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+ factories_by_setting = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+
+ /* Register internal factories first */
+ for (iter = internal_types; iter; iter = iter->next) {
+ GType ftype = (GType) GPOINTER_TO_SIZE (iter->data);
+
+ factory = (NMDeviceFactory *) g_object_new (ftype, NULL);
+ g_assert (factory);
+ _add_factory (factory, FALSE, "internal", callback, user_data);
+ }
+
+ 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 (_add_factory (factory, TRUE, g_module_name (plugin), callback, user_data))
+ g_module_make_resident (plugin);
+ else
+ g_module_close (plugin);
+
+ g_object_unref (factory);
+ }
+ g_strfreev (paths);
+}
+
diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h
index ce672b8bfb..c6e4fa6914 100644
--- a/src/devices/nm-device-factory.h
+++ b/src/devices/nm-device-factory.h
@@ -66,14 +66,19 @@ struct _NMDeviceFactory {
GTypeInterface g_iface;
/**
- * get_device_type:
+ * get_supported_types:
* @factory: the #NMDeviceFactory
+ * @out_link_types: on return, a %NM_LINK_TYPE_NONE terminated
+ * list of #NMLinkType that the plugin supports
+ * @out_setting_types: on return, a %NULL terminated list of
+ * base-type #NMSetting names that the plugin can create devices for
*
- * This function MUST be implemented.
- *
- * Returns: the #NMDeviceType that this plugin creates
+ * Returns the #NMLinkType and #NMSetting names that this plugin
+ * supports. This function MUST be implemented.
*/
- NMDeviceType (*get_device_type) (NMDeviceFactory *factory);
+ void (*get_supported_types) (NMDeviceFactory *factory,
+ const NMLinkType **out_link_types,
+ const char ***out_setting_types);
/**
* start:
@@ -87,15 +92,17 @@ struct _NMDeviceFactory {
/**
* new_link:
* @factory: the #NMDeviceFactory
- * @link: the new link
+ * @plink: the new link
* @error: error if the link could be claimed but an error occurred
*
* The NetworkManager core was notified of a new link which the plugin
* may want to claim and create a #NMDevice subclass for. If the link
- * represents a device the factory is capable of claiming, but the device
- * could not be created, %NULL should be returned and @error should be set.
- * %NULL should always be returned and @error should never be set if the
- * factory cannot create devices for the type which @link represents.
+ * represents a device which the factory does not support, or the link
+ * is supported but the device could not be created, %NULL should be
+ * returned and @error should be set.
+ *
+ * @plink is guaranteed to be one of the types the factory returns in
+ * get_supported_types().
*
* Returns: the #NMDevice if the link was claimed and created, %NULL if not
*/
@@ -151,7 +158,9 @@ struct _NMDeviceFactory {
GType nm_device_factory_get_type (void);
-NMDeviceType nm_device_factory_get_device_type (NMDeviceFactory *factory);
+void nm_device_factory_get_supported_types (NMDeviceFactory *factory,
+ const NMLinkType **out_link_types,
+ const char ***out_setting_types);
void nm_device_factory_start (NMDeviceFactory *factory);
@@ -168,15 +177,33 @@ NMDevice * nm_device_factory_create_virtual_device_for_connection (NMDeviceFacto
gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory,
GObject *component);
+#define NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(...) \
+ { static const NMLinkType _df_links[] = { __VA_ARGS__, NM_LINK_TYPE_NONE }; *out_link_types = _df_links; }
+#define NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(...) \
+ { static const char *_df_settings[] = { __VA_ARGS__, NULL }; *out_setting_types = _df_settings; }
+
+extern const NMLinkType _nm_device_factory_no_default_links[];
+extern const char *_nm_device_factory_no_default_settings[];
+
+#define NM_DEVICE_FACTORY_DECLARE_TYPES(...) \
+ static void \
+ get_supported_types (NMDeviceFactory *factory, \
+ const NMLinkType **out_link_types, \
+ const char ***out_setting_types) \
+ { \
+ *out_link_types = _nm_device_factory_no_default_links; \
+ *out_setting_types = _nm_device_factory_no_default_settings; \
+ \
+ { __VA_ARGS__; } \
+ } \
+ \
+
/**************************************************************************
* INTERNAL DEVICE FACTORY FUNCTIONS - devices provided by plugins should
* not use these functions.
**************************************************************************/
-#define DEFINE_DEVICE_FACTORY_INTERNAL(upper, mixed, lower, dfi_code) \
- DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(upper, mixed, lower, upper, dfi_code)
-
-#define DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(upper, mixed, lower, devtype, dfi_code) \
+#define NM_DEVICE_FACTORY_DEFINE_INTERNAL(upper, mixed, lower, st_code, dfi_code) \
typedef GObject NM##mixed##Factory; \
typedef GObjectClass NM##mixed##FactoryClass; \
\
@@ -198,16 +225,12 @@ gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory,
g_type_ensure (NM_TYPE_##upper##_FACTORY); \
} \
\
- static NMDeviceType \
- get_device_type (NMDeviceFactory *factory) \
- { \
- return NM_DEVICE_TYPE_##devtype; \
- } \
+ NM_DEVICE_FACTORY_DECLARE_TYPES(st_code) \
\
static void \
device_factory_interface_init (NMDeviceFactory *factory_iface) \
{ \
- factory_iface->get_device_type = get_device_type; \
+ factory_iface->get_supported_types = get_supported_types; \
dfi_code \
} \
\
@@ -222,6 +245,22 @@ gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory,
}
void _nm_device_factory_internal_register_type (GType factory_type);
-const GSList *nm_device_factory_get_internal_factory_types (void);
+
+/**************************************************************************
+ * PRIVATE FACTORY FUNCTIONS - for factory consumers (eg, NMManager).
+ **************************************************************************/
+
+typedef void (*NMDeviceFactoryManagerFactoryFunc) (NMDeviceFactory *factory,
+ gpointer user_data);
+
+void nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc callback,
+ gpointer user_data);
+
+NMDeviceFactory * nm_device_factory_manager_find_factory_for_link_type (NMLinkType link_type);
+
+NMDeviceFactory * nm_device_factory_manager_find_factory_for_connection (NMConnection *connection);
+
+void nm_device_factory_manager_for_each_factory (NMDeviceFactoryManagerFactoryFunc callback,
+ gpointer user_data);
#endif /* __NETWORKMANAGER_DEVICE_FACTORY_H__ */
diff --git a/src/devices/nm-device-gre.c b/src/devices/nm-device-gre.c
index 6313bfd714..9e592b51f9 100644
--- a/src/devices/nm-device-gre.c
+++ b/src/devices/nm-device-gre.c
@@ -269,17 +269,15 @@ nm_device_gre_class_init (NMDeviceGreClass *klass)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_GRE || plink->type == NM_LINK_TYPE_GRETAP) {
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GRE,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_TYPE_DESC, "Gre",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
- NULL);
- }
- return NULL;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GRE,
+ NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_TYPE_DESC, "Gre",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
+ NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(GRE, Gre, gre, ETHERNET, \
- factory_iface->new_link = new_link; \
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (GRE, Gre, gre,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP),
+ factory_iface->new_link = new_link;
)
diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c
index 0a3b17c708..9f2119abac 100644
--- a/src/devices/nm-device-infiniband.c
+++ b/src/devices/nm-device-infiniband.c
@@ -295,14 +295,11 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_INFINIBAND) {
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_TYPE_DESC, "InfiniBand",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND,
- NULL);
- }
- return NULL;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND,
+ NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_TYPE_DESC, "InfiniBand",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND,
+ NULL);
}
static NMDevice *
@@ -315,23 +312,27 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
int p_key, parent_ifindex;
const char *iface;
- if (!nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME))
+ if (!NM_IS_DEVICE_INFINIBAND (parent)) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Parent interface %s must be an InfiniBand interface",
+ nm_device_get_iface (parent));
return NULL;
-
- g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (parent), NULL);
+ }
s_infiniband = nm_connection_get_setting_infiniband (connection);
iface = nm_setting_infiniband_get_virtual_interface_name (s_infiniband);
- g_return_val_if_fail (iface != NULL, NULL);
+ g_assert (iface);
parent_ifindex = nm_device_get_ifindex (parent);
p_key = nm_setting_infiniband_get_p_key (s_infiniband);
if ( !nm_platform_infiniband_partition_add (NM_PLATFORM_GET, parent_ifindex, p_key)
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
- nm_log_warn (LOGD_DEVICE | LOGD_INFINIBAND, "(%s): failed to add InfiniBand P_Key interface for '%s': %s",
- iface, nm_connection_get_id (connection),
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create InfiniBand P_Key interface '%s' for '%s': %s",
+ iface,
+ nm_connection_get_id (connection),
nm_platform_get_error_msg (NM_PLATFORM_GET));
return NULL;
}
@@ -344,8 +345,10 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL(INFINIBAND, Infiniband, infiniband, \
- factory_iface->new_link = new_link; \
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (INFINIBAND, Infiniband, infiniband,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_INFINIBAND)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_INFINIBAND_SETTING_NAME),
+ factory_iface->new_link = new_link;
factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
)
diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c
index 608e541db0..4235b62783 100644
--- a/src/devices/nm-device-macvlan.c
+++ b/src/devices/nm-device-macvlan.c
@@ -177,17 +177,15 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_MACVLAN || plink->type == NM_LINK_TYPE_MACVTAP) {
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_MACVLAN,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_TYPE_DESC, "Macvlan",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
- NULL);
- }
- return NULL;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_MACVLAN,
+ NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_TYPE_DESC, "Macvlan",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
+ NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(MACVLAN, Macvlan, macvlan, ETHERNET, \
- factory_iface->new_link = new_link; \
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (MACVLAN, Macvlan, macvlan,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP),
+ factory_iface->new_link = new_link;
)
diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c
index 4f4ed69b25..54cbbf82f3 100644
--- a/src/devices/nm-device-tun.c
+++ b/src/devices/nm-device-tun.c
@@ -278,8 +278,10 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
mode = "tun";
else if (plink->type == NM_LINK_TYPE_TAP)
mode = "tap";
- else
- return NULL;
+ else {
+ g_warn_if_reached ();
+ mode = "unknown";
+ }
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TUN,
NM_DEVICE_PLATFORM_DEVICE, plink,
@@ -289,7 +291,8 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(TUN, Tun, tun, GENERIC, \
- factory_iface->new_link = new_link; \
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (TUN, Tun, tun,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP),
+ factory_iface->new_link = new_link;
)
diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c
index 5eba1b3c39..ba0b304b0b 100644
--- a/src/devices/nm-device-veth.c
+++ b/src/devices/nm-device-veth.c
@@ -167,17 +167,15 @@ nm_device_veth_class_init (NMDeviceVethClass *klass)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_VETH) {
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VETH,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_TYPE_DESC, "Veth",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
- NULL);
- }
- return NULL;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VETH,
+ NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_TYPE_DESC, "Veth",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
+ NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(VETH, Veth, veth, ETHERNET, \
- factory_iface->new_link = new_link; \
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (VETH, Veth, veth,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VETH),
+ factory_iface->new_link = new_link;
)
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index 5513d73abb..55292173af 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -40,6 +40,7 @@
#include "nm-device-factory.h"
#include "nm-manager.h"
#include "nm-core-internal.h"
+#include "gsystem-local-alloc.h"
#include "nm-device-vlan-glue.h"
@@ -660,25 +661,13 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
int parent_ifindex = -1;
NMDevice *parent, *device;
- if (plink->type != NM_LINK_TYPE_VLAN)
- return NULL;
-
- /* Have to find the parent device */
+ /* Find the parent device */
if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, plink->ifindex, &parent_ifindex, NULL)) {
- nm_log_err (LOGD_HW, "(%s): failed to get VLAN parent ifindex", plink->name);
+ g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "VLAN parent ifindex unknown");
return NULL;
}
-
parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex);
- if (!parent) {
- /* If udev signaled the VLAN interface before it signaled
- * the VLAN's parent at startup we may not know about the
- * parent device yet. But we'll find it on the second pass
- * from nm_manager_start().
- */
- nm_log_dbg (LOGD_HW, "(%s): VLAN parent interface unknown", plink->name);
- return NULL;
- }
device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN,
NM_DEVICE_PLATFORM_DEVICE, plink,
@@ -688,6 +677,8 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN,
NULL);
if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) {
+ g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "VLAN initialization failed");
g_object_unref (device);
device = NULL;
}
@@ -703,15 +694,16 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
{
NMDevice *device;
NMSettingVlan *s_vlan;
- char *iface;
+ gs_free char *iface = NULL;
- if (!nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME))
+ if (!NM_IS_DEVICE (parent)) {
+ g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "VLAN interfaces must have parents");
return NULL;
-
- g_return_val_if_fail (NM_IS_DEVICE (parent), NULL);
+ }
s_vlan = nm_connection_get_setting_vlan (connection);
- g_return_val_if_fail (s_vlan != NULL, NULL);
+ g_assert (s_vlan);
iface = g_strdup (nm_connection_get_interface_name (connection));
if (!iface) {
@@ -725,9 +717,11 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
nm_setting_vlan_get_id (s_vlan),
nm_setting_vlan_get_flags (s_vlan))
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
- nm_log_warn (LOGD_DEVICE | LOGD_VLAN, "(%s) failed to add VLAN interface for '%s'",
- iface, nm_connection_get_id (connection));
- g_free (iface);
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create VLAN interface '%s' for '%s': %s",
+ iface,
+ nm_connection_get_id (connection),
+ nm_platform_get_error_msg (NM_PLATFORM_GET));
return NULL;
}
@@ -738,8 +732,10 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NM_DEVICE_TYPE_DESC, "VLAN",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN,
NULL);
- g_free (iface);
if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create VLAN interface '%s' for '%s': initialization failed",
+ iface, nm_connection_get_id (connection));
g_object_unref (device);
device = NULL;
}
@@ -747,8 +743,10 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
return device;
}
-DEFINE_DEVICE_FACTORY_INTERNAL(VLAN, Vlan, vlan, \
- factory_iface->new_link = new_link; \
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (VLAN, Vlan, vlan,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VLAN)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VLAN_SETTING_NAME),
+ factory_iface->new_link = new_link;
factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
)
diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c
index 25ee804dfa..c0492aee34 100644
--- a/src/devices/nm-device-vxlan.c
+++ b/src/devices/nm-device-vxlan.c
@@ -355,17 +355,15 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_VXLAN) {
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VXLAN,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_TYPE_DESC, "Vxlan",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
- NULL);
- }
- return NULL;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VXLAN,
+ NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_TYPE_DESC, "Vxlan",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
+ NULL);
}
-DEFINE_DEVICE_FACTORY_INTERNAL_WITH_DEVTYPE(VXLAN, Vxlan, vxlan, GENERIC, \
- factory_iface->new_link = new_link; \
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (VXLAN, Vxlan, vxlan,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VXLAN),
+ factory_iface->new_link = new_link;
)
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index 3f31244ec2..b52b00253b 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -696,8 +696,6 @@ release_slave (NMDevice *device,
NMDevice *
nm_device_team_new (NMPlatformLink *platform_device)
{
- g_return_val_if_fail (platform_device != NULL, NULL);
-
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM,
NM_DEVICE_PLATFORM_DEVICE, platform_device,
NM_DEVICE_DRIVER, "team",
@@ -710,20 +708,16 @@ nm_device_team_new (NMPlatformLink *platform_device)
NMDevice *
nm_device_team_new_for_connection (NMConnection *connection, GError **error)
{
- const char *iface;
-
- g_return_val_if_fail (connection != NULL, NULL);
+ const char *iface = nm_connection_get_interface_name (connection);
- iface = nm_connection_get_interface_name (connection);
- g_return_val_if_fail (iface != NULL, NULL);
+ g_assert (iface);
if ( !nm_platform_team_add (NM_PLATFORM_GET, iface)
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
- g_set_error (error,
- NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_CREATION_FAILED,
- "failed to create team master interface '%s' for connection '%s': %s",
- iface, nm_connection_get_id (connection),
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create team master interface '%s' for '%s': %s",
+ iface,
+ nm_connection_get_id (connection),
nm_platform_get_error_msg (NM_PLATFORM_GET));
return NULL;
}
diff --git a/src/devices/team/nm-team-factory.c b/src/devices/team/nm-team-factory.c
index cb887cac24..f21f07502c 100644
--- a/src/devices/team/nm-team-factory.c
+++ b/src/devices/team/nm-team-factory.c
@@ -50,9 +50,7 @@ nm_device_factory_create (GError **error)
static NMDevice *
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
{
- if (plink->type == NM_LINK_TYPE_TEAM)
- return nm_device_team_new (plink);
- return NULL;
+ return nm_device_team_new (plink);
}
static NMDevice *
@@ -61,16 +59,13 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NMDevice *parent,
GError **error)
{
- if (nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME))
- return nm_device_team_new_for_connection (connection, error);
- return NULL;
+ return nm_device_team_new_for_connection (connection, error);
}
-static NMDeviceType
-get_device_type (NMDeviceFactory *factory)
-{
- return NM_DEVICE_TYPE_TEAM;
-}
+NM_DEVICE_FACTORY_DECLARE_TYPES (
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_TEAM)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_TEAM_SETTING_NAME)
+)
/************************************************************************/
@@ -84,7 +79,7 @@ device_factory_interface_init (NMDeviceFactory *factory_iface)
{
factory_iface->new_link = new_link;
factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
- factory_iface->get_device_type = get_device_type;
+ factory_iface->get_supported_types = get_supported_types;
}
static void
diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c
index 4093c61239..19578b3d58 100644
--- a/src/devices/wifi/nm-wifi-factory.c
+++ b/src/devices/wifi/nm-wifi-factory.c
@@ -23,6 +23,8 @@
#include <gmodule.h>
#include "nm-device-factory.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-olpc-mesh.h"
#include "nm-device-wifi.h"
#include "nm-device-olpc-mesh.h"
#include "nm-settings-connection.h"
@@ -63,20 +65,19 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
return nm_device_wifi_new (plink);
else if (plink->type == NM_LINK_TYPE_OLPC_MESH)
return nm_device_olpc_mesh_new (plink);
- return NULL;
+ g_assert_not_reached ();
}
-static NMDeviceType
-get_device_type (NMDeviceFactory *factory)
-{
- return NM_DEVICE_TYPE_WIFI;
-}
+NM_DEVICE_FACTORY_DECLARE_TYPES (
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_WIFI, NM_LINK_TYPE_OLPC_MESH)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_OLPC_MESH_SETTING_NAME)
+)
static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
factory_iface->new_link = new_link;
- factory_iface->get_device_type = get_device_type;
+ factory_iface->get_supported_types = get_supported_types;
}
static void
diff --git a/src/devices/wimax/nm-wimax-factory.c b/src/devices/wimax/nm-wimax-factory.c
index 39e9a28738..ffda4674e5 100644
--- a/src/devices/wimax/nm-wimax-factory.c
+++ b/src/devices/wimax/nm-wimax-factory.c
@@ -25,6 +25,7 @@
#include "nm-device-factory.h"
#include "nm-device-wimax.h"
#include "nm-platform.h"
+#include "nm-setting-wimax.h"
#define NM_TYPE_WIMAX_FACTORY (nm_wimax_factory_get_type ())
#define NM_WIMAX_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_WIMAX_FACTORY, NMWimaxFactory))
@@ -66,17 +67,16 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
return (NMDevice *) nm_device_wimax_new (plink);
}
-static NMDeviceType
-get_device_type (NMDeviceFactory *factory)
-{
- return NM_DEVICE_TYPE_WIMAX;
-}
+NM_DEVICE_FACTORY_DECLARE_TYPES (
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_WIMAX)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_WIMAX_SETTING_NAME)
+)
static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
factory_iface->new_link = new_link;
- factory_iface->get_device_type = get_device_type;
+ factory_iface->get_supported_types = get_supported_types;
}
static void
diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c
index 2b9c3d4dd0..b6870d0dde 100644
--- a/src/devices/wwan/nm-wwan-factory.c
+++ b/src/devices/wwan/nm-wwan-factory.c
@@ -25,6 +25,8 @@
#include "nm-device-factory.h"
#include "nm-wwan-factory.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-cdma.h"
#include "nm-modem-manager.h"
#include "nm-device-modem.h"
#include "nm-logging.h"
@@ -87,11 +89,10 @@ modem_added_cb (NMModemManager *manager,
}
-static NMDeviceType
-get_device_type (NMDeviceFactory *factory)
-{
- return NM_DEVICE_TYPE_MODEM;
-}
+NM_DEVICE_FACTORY_DECLARE_TYPES (
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_WWAN_ETHERNET)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_GSM_SETTING_NAME, NM_SETTING_CDMA_SETTING_NAME)
+)
static void
start (NMDeviceFactory *factory)
@@ -115,7 +116,7 @@ nm_wwan_factory_init (NMWwanFactory *self)
static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
- factory_iface->get_device_type = get_device_type;
+ factory_iface->get_supported_types = get_supported_types;
factory_iface->start = start;
}
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 2705efd4ea..172b4d194b 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>
@@ -178,9 +176,6 @@ typedef struct {
gboolean prop_filter_added;
NMRfkillManager *rfkill_mgr;
- /* List of NMDeviceFactoryFunc pointers sorted in priority order */
- GSList *factories;
-
NMSettings *settings;
char *hostname;
@@ -1053,7 +1048,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;
@@ -1090,6 +1085,19 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
}
}
+ 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;
+ }
+
/* 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.
@@ -1098,24 +1106,10 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
nm_owned = !nm_platform_link_exists (NM_PLATFORM_GET, 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;
- }
- }
-
+ device = nm_device_factory_create_virtual_device_for_connection (factory,
+ connection,
+ parent,
+ error);
if (device) {
if (nm_owned)
nm_device_set_nm_owned (device);
@@ -1126,16 +1120,6 @@ 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--;
@@ -1952,124 +1936,10 @@ factory_component_added_cb (NMDeviceFactory *factory,
return notify_component_added (NM_MANAGER (user_data), component);
}
-#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;
-}
-
-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,
@@ -2079,80 +1949,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);
}
/*******************************************************************/
@@ -2164,8 +1960,8 @@ platform_link_added (NMManager *self,
NMPlatformReason reason)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+ NMDeviceFactory *factory;
NMDevice *device = NULL;
- GSList *iter;
GError *error = NULL;
g_return_if_fail (ifindex > 0);
@@ -2176,41 +1972,31 @@ platform_link_added (NMManager *self,
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);
+ /* Ignore Bluetooth PAN interfaces; they are handled by their NMDeviceBt
+ * parent and don't get a separate interface.
+ */
+ if (plink->type == NM_LINK_TYPE_BNEP)
+ return;
+ /* Try registered device factories */
+ factory = nm_device_factory_manager_find_factory_for_link_type (plink->type);
+ if (factory) {
device = nm_device_factory_new_link (factory, plink, &error);
- if (device && NM_IS_DEVICE (device)) {
- g_assert_no_error (error);
- break; /* success! */
- }
-
- 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)");
+ if (!device) {
+ 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 (plink->type == NM_LINK_TYPE_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_OLPC_MESH:
case NM_LINK_TYPE_TEAM:
case NM_LINK_TYPE_WIFI:
@@ -4233,11 +4019,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 */
@@ -4269,8 +4060,7 @@ 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 (NM_PLATFORM_GET);
@@ -4875,7 +4665,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;
}
@@ -5110,13 +4900,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;
@@ -5188,14 +4983,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;