mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-08 18:50:18 +01:00
core: let device plugins advertise supported link and setting types
Instead of looping over all plugins and asking each plugin whether it
can handle a link or a connection, have them advertise the link and
connection types they support, and use that when creating new devices.
(cherry picked from commit 71bde20c30)
This commit is contained in:
parent
998f1cf732
commit
c174da8e13
20 changed files with 659 additions and 501 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_device_type (factory);
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
const char *iface = nm_connection_get_interface_name (connection);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
311
src/nm-manager.c
311
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)
|
||||
static void
|
||||
_register_device_factory (NMDeviceFactory *factory, gpointer user_data)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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)");
|
||||
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;
|
||||
|
||||
/* 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_log_warn (LOGD_HW, "%s: factory failed to create device: %s",
|
||||
plink->name, error->message);
|
||||
g_clear_error (&error);
|
||||
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;
|
||||
}
|
||||
|
|
@ -5109,6 +4899,12 @@ 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)
|
||||
{
|
||||
|
|
@ -5116,7 +4912,6 @@ dispose (GObject *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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue