From ce4f2a4bd6270400e9d32c98ceaf8fa8f0b5df8c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 17 Apr 2013 10:41:15 -0400 Subject: [PATCH] core, libnm-glib: add NMDeviceGeneric Add NMDeviceGeneric, to provide generic support for unknown device types, and create NMDeviceGenerics for those devices that NM previously was ignoring. Allow NMSettingGeneric connections to be activated on (managed) NMDeviceGenerics. --- include/NetworkManager.h | 3 + introspection/Makefile.am | 1 + introspection/nm-device-generic.xml | 21 +++ libnm-glib/Makefile.am | 2 + libnm-glib/libnm-glib.ver | 4 + libnm-glib/nm-device-generic.c | 246 ++++++++++++++++++++++++++++ libnm-glib/nm-device-generic.h | 78 +++++++++ libnm-glib/nm-device.c | 3 + src/Makefile.am | 6 + src/nm-device-generic.c | 145 ++++++++++++++++ src/nm-device-generic.h | 65 ++++++++ src/nm-manager.c | 26 ++- src/nm-udev-manager.c | 24 +-- 13 files changed, 597 insertions(+), 27 deletions(-) create mode 100644 introspection/nm-device-generic.xml create mode 100644 libnm-glib/nm-device-generic.c create mode 100644 libnm-glib/nm-device-generic.h create mode 100644 src/nm-device-generic.c create mode 100644 src/nm-device-generic.h diff --git a/include/NetworkManager.h b/include/NetworkManager.h index d45ad07b3f..737ecc802f 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -53,6 +53,7 @@ #define NM_DBUS_INTERFACE_DEVICE_BOND NM_DBUS_INTERFACE_DEVICE ".Bond" #define NM_DBUS_INTERFACE_DEVICE_VLAN NM_DBUS_INTERFACE_DEVICE ".Vlan" #define NM_DBUS_INTERFACE_DEVICE_BRIDGE NM_DBUS_INTERFACE_DEVICE ".Bridge" +#define NM_DBUS_INTERFACE_DEVICE_GENERIC NM_DBUS_INTERFACE_DEVICE ".Generic" #define NM_DBUS_IFACE_SETTINGS "org.freedesktop.NetworkManager.Settings" @@ -98,6 +99,7 @@ typedef enum { /** * NMDeviceType: * @NM_DEVICE_TYPE_UNKNOWN: unknown device + * @NM_DEVICE_TYPE_GENERIC: generic support for unrecognized device types * @NM_DEVICE_TYPE_ETHERNET: a wired ethernet device * @NM_DEVICE_TYPE_WIFI: an 802.11 WiFi device * @NM_DEVICE_TYPE_UNUSED1: not used @@ -131,6 +133,7 @@ typedef enum { NM_DEVICE_TYPE_VLAN = 11, NM_DEVICE_TYPE_ADSL = 12, NM_DEVICE_TYPE_BRIDGE = 13, + NM_DEVICE_TYPE_GENERIC = 14, } NMDeviceType; /** diff --git a/introspection/Makefile.am b/introspection/Makefile.am index 3850a23464..82e9fba8d8 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -15,6 +15,7 @@ EXTRA_DIST = \ nm-device-bond.xml \ nm-device-bridge.xml \ nm-device-vlan.xml \ + nm-device-generic.xml \ nm-device.xml \ nm-ip4-config.xml \ nm-ip6-config.xml \ diff --git a/introspection/nm-device-generic.xml b/introspection/nm-device-generic.xml new file mode 100644 index 0000000000..7cd3d1afc3 --- /dev/null +++ b/introspection/nm-device-generic.xml @@ -0,0 +1,21 @@ + + + + + + + + Hardware address of the device. + + + + + + + A dictionary mapping property names to variant boxed values + + + + + + diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 7f6ee1b339..974cc0d289 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -66,6 +66,7 @@ libnminclude_HEADERS = \ nm-device-bond.h \ nm-device-bridge.h \ nm-device-vlan.h \ + nm-device-generic.h \ nm-access-point.h \ nm-ip4-config.h \ nm-device-modem.h \ @@ -102,6 +103,7 @@ libnm_glib_la_csources = \ nm-device-bond.c \ nm-device-bridge.c \ nm-device-vlan.c \ + nm-device-generic.c \ nm-access-point.c \ nm-ip4-config.c \ nm-device-modem.c \ diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 1848171e6e..d066067cfa 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -102,6 +102,10 @@ global: nm_device_ethernet_get_type; nm_device_ethernet_new; nm_device_filter_connections; + nm_device_generic_error_get_type; + nm_device_generic_error_quark; + nm_device_generic_get_hw_address; + nm_device_generic_get_type; nm_device_get_active_connection; nm_device_get_autoconnect; nm_device_get_available_connections; diff --git a/libnm-glib/nm-device-generic.c b/libnm-glib/nm-device-generic.c new file mode 100644 index 0000000000..170b9b8fd8 --- /dev/null +++ b/libnm-glib/nm-device-generic.c @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include + +#include + +#include "nm-device-generic.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-setting-generic.h" + +G_DEFINE_TYPE (NMDeviceGeneric, nm_device_generic, NM_TYPE_DEVICE) + +#define NM_DEVICE_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericPrivate)) + +typedef struct { + DBusGProxy *proxy; + + char *hw_address; +} NMDeviceGenericPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + + LAST_PROP +}; + +#define DBUS_PROP_HW_ADDRESS "HwAddress" + +/** + * nm_device_generic_error_quark: + * + * Registers an error quark for #NMDeviceGeneric if necessary. + * + * Returns: the error quark used for #NMDeviceGeneric errors. + * + * Since: 0.9.10 + **/ +GQuark +nm_device_generic_error_quark (void) +{ + static GQuark quark = 0; + + if (G_UNLIKELY (quark == 0)) + quark = g_quark_from_static_string ("nm-device-generic-error-quark"); + return quark; +} + +/** + * nm_device_generic_new: + * @connection: the #DBusGConnection + * @path: the DBus object path of the device + * + * Creates a new #NMDeviceGeneric. + * + * Returns: (transfer full): a new device + * + * Since: 0.9.10 + **/ +GObject * +nm_device_generic_new (DBusGConnection *connection, const char *path) +{ + GObject *device; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); + + device = g_object_new (NM_TYPE_DEVICE_GENERIC, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); + _nm_object_ensure_inited (NM_OBJECT (device)); + return device; +} + +/** + * nm_device_generic_get_hw_address: + * @device: a #NMDeviceGeneric + * + * Gets the hardware address of the #NMDeviceGeneric + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + * + * Since: 0.9.10 + **/ +const char * +nm_device_generic_get_hw_address (NMDeviceGeneric *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_GENERIC (device), NULL); + + _nm_object_ensure_inited (NM_OBJECT (device)); + return NM_DEVICE_GENERIC_GET_PRIVATE (device)->hw_address; +} + +/***********************************************************/ + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingConnection *s_con; + const char *ctype, *iface_name; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + ctype = nm_setting_connection_get_connection_type (s_con); + if (strcmp (ctype, NM_SETTING_GENERIC_SETTING_NAME) != 0) { + g_set_error (error, NM_DEVICE_GENERIC_ERROR, NM_DEVICE_GENERIC_ERROR_NOT_GENERIC_CONNECTION, + "The connection was not a generic connection."); + return FALSE; + } + + iface_name = nm_setting_connection_get_interface_name (s_con); + if (!iface_name) { + g_set_error (error, NM_DEVICE_GENERIC_ERROR, NM_DEVICE_GENERIC_ERROR_MISSING_INTERFACE_NAME, + "The connection did not specify an interface name."); + return FALSE; + } + + return NM_DEVICE_CLASS (nm_device_generic_parent_class)->connection_compatible (device, connection, error); +} + +/***********************************************************/ + +static void +nm_device_generic_init (NMDeviceGeneric *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_GENERIC); +} + +static void +register_properties (NMDeviceGeneric *device) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (device); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_GENERIC_HW_ADDRESS, &priv->hw_address }, + { NULL }, + }; + + _nm_object_register_properties (NM_OBJECT (device), + priv->proxy, + property_info); +} + +static void +constructed (GObject *object) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); + + G_OBJECT_CLASS (nm_device_generic_parent_class)->constructed (object); + + priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE_GENERIC); + register_properties (NM_DEVICE_GENERIC (object)); +} + +static void +dispose (GObject *object) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); + + g_clear_object (&priv->proxy); + + G_OBJECT_CLASS (nm_device_generic_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); + + g_free (priv->hw_address); + + G_OBJECT_CLASS (nm_device_generic_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); + + _nm_object_ensure_inited (NM_OBJECT (object)); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, priv->hw_address); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_generic_class_init (NMDeviceGenericClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceGenericPrivate)); + + object_class->constructed = constructed; + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + + device_class->connection_compatible = connection_compatible; + + /** + * NMDeviceGeneric:hw-address: + * + * The hardware address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_GENERIC_HW_ADDRESS, + "Hardware Address", + "Hardware address", + NULL, + G_PARAM_READABLE)); +} + diff --git a/libnm-glib/nm-device-generic.h b/libnm-glib/nm-device-generic.h new file mode 100644 index 0000000000..492e3c598f --- /dev/null +++ b/libnm-glib/nm-device-generic.h @@ -0,0 +1,78 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_GENERIC_H +#define NM_DEVICE_GENERIC_H + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_GENERIC (nm_device_generic_get_type ()) +#define NM_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGeneric)) +#define NM_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) +#define NM_IS_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GENERIC)) +#define NM_IS_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GENERIC)) +#define NM_DEVICE_GENERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) + +/** + * NMDeviceGenericError: + * @NM_DEVICE_GENERIC_ERROR_UNKNOWN: unknown or unclassified error + * @NM_DEVICE_GENERIC_ERROR_NOT_GENERIC_CONNECTION: the connection was not of generic type + * @NM_DEVICE_GENERIC_ERROR_MISSING_INTERFACE_NAME: the connection did not specify the interface name + */ +typedef enum { + NM_DEVICE_GENERIC_ERROR_UNKNOWN = 0, /*< nick=UnknownError >*/ + NM_DEVICE_GENERIC_ERROR_NOT_GENERIC_CONNECTION, /*< nick=NotGenericConnection >*/ + NM_DEVICE_GENERIC_ERROR_MISSING_INTERFACE_NAME, /*< nick=MissingInterfaceName >*/ +} NMDeviceGenericError; + +#define NM_DEVICE_GENERIC_ERROR nm_device_generic_error_quark () +GQuark nm_device_generic_error_quark (void); + +#define NM_DEVICE_GENERIC_HW_ADDRESS "hw-address" + +typedef struct { + NMDevice parent; +} NMDeviceGeneric; + +typedef struct { + NMDeviceClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); + void (*_reserved5) (void); + void (*_reserved6) (void); +} NMDeviceGenericClass; + +GType nm_device_generic_get_type (void); + +GObject *nm_device_generic_new (DBusGConnection *connection, const char *path); + +const char *nm_device_generic_get_hw_address (NMDeviceGeneric *device); + +G_END_DECLS + +#endif /* NM_DEVICE_GENERIC_H */ diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index d952914b5a..cda3a26381 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -37,6 +37,7 @@ #include "nm-device-bond.h" #include "nm-device-bridge.h" #include "nm-device-vlan.h" +#include "nm-device-generic.h" #include "nm-device.h" #include "nm-device-private.h" #include "nm-object-private.h" @@ -301,6 +302,8 @@ _nm_device_gtype_from_dtype (NMDeviceType dtype) return NM_TYPE_DEVICE_BRIDGE; case NM_DEVICE_TYPE_VLAN: return NM_TYPE_DEVICE_VLAN; + case NM_DEVICE_TYPE_GENERIC: + return NM_TYPE_DEVICE_GENERIC; default: g_warning ("Unknown device type %d", dtype); return G_TYPE_INVALID; diff --git a/src/Makefile.am b/src/Makefile.am index 113b527606..b2162d7880 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -149,6 +149,8 @@ NetworkManager_SOURCES = \ nm-device-bridge.h \ nm-device-vlan.c \ nm-device-vlan.h \ + nm-device-generic.c \ + nm-device-generic.h \ nm-wifi-ap.c \ nm-wifi-ap.h \ nm-wifi-ap-utils.c \ @@ -276,6 +278,9 @@ nm-dhcp6-config-glue.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $< +nm-device-generic-glue.h: $(top_srcdir)/introspection/nm-device-generic.xml + $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_generic --mode=glib-server --output=$@ $< + BUILT_SOURCES = \ nm-access-point-glue.h \ nm-manager-glue.h \ @@ -290,6 +295,7 @@ BUILT_SOURCES = \ nm-device-olpc-mesh-glue.h \ nm-device-bt-glue.h \ nm-device-modem-glue.h \ + nm-device-generic-glue.h \ nm-ip4-config-glue.h \ nm-ip6-config-glue.h \ nm-active-connection-glue.h \ diff --git a/src/nm-device-generic.c b/src/nm-device-generic.c new file mode 100644 index 0000000000..043de7eaf8 --- /dev/null +++ b/src/nm-device-generic.c @@ -0,0 +1,145 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-device-generic.h" +#include "nm-device-private.h" +#include "nm-enum-types.h" +#include "nm-properties-changed-signal.h" +#include "nm-utils.h" + +#include "nm-device-generic-glue.h" + +G_DEFINE_TYPE (NMDeviceGeneric, nm_device_generic, NM_TYPE_DEVICE) + +#define NM_DEVICE_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericPrivate)) + +typedef struct { + int dummy; +} NMDeviceGenericPrivate; + +enum { + PROPERTIES_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +#define NM_DEVICE_GENERIC_ERROR (nm_device_generic_error_quark ()) + +static GQuark +nm_device_generic_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-device-generic-error"); + return quark; +} + +/**************************************************************/ + +static guint32 +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_NM_SUPPORTED; +} + +static gboolean +is_available (NMDevice *device) +{ + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, + NMConnection *connection, + GError **error) +{ + NMSettingConnection *s_con; + + if (!NM_DEVICE_CLASS (nm_device_generic_parent_class)->check_connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_GENERIC_SETTING_NAME)) { + g_set_error (error, + NM_DEVICE_GENERIC_ERROR, NM_DEVICE_GENERIC_ERROR_CONNECTION_NOT_GENERIC, + "The connection was not a generic connection."); + return FALSE; + } + + s_con = nm_connection_get_setting_connection (connection); + if (!nm_setting_connection_get_interface_name (s_con)) { + g_set_error (error, + NM_DEVICE_GENERIC_ERROR, NM_DEVICE_GENERIC_ERROR_CONNECTION_INVALID, + "The connection did not specify an interface name."); + return FALSE; + } + + return TRUE; +} + +/**************************************************************/ + +NMDevice * +nm_device_generic_new (const char *udi, + const char *iface, + const char *driver) +{ + g_return_val_if_fail (udi != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GENERIC, + NM_DEVICE_UDI, udi, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, driver, + NM_DEVICE_TYPE_DESC, "Generic", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NULL); +} + +static void +nm_device_generic_init (NMDeviceGeneric *self) +{ + nm_device_set_default_unmanaged (NM_DEVICE (self), TRUE); +} + +static void +nm_device_generic_class_init (NMDeviceGenericClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceGenericPrivate)); + + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->is_available = is_available; + parent_class->check_connection_compatible = check_connection_compatible; + + /* signals */ + signals[PROPERTIES_CHANGED] = + nm_properties_changed_signal_new (object_class, + G_STRUCT_OFFSET (NMDeviceGenericClass, properties_changed)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_generic_object_info); + + dbus_g_error_domain_register (NM_DEVICE_GENERIC_ERROR, NULL, NM_TYPE_DEVICE_GENERIC_ERROR); +} diff --git a/src/nm-device-generic.h b/src/nm-device-generic.h new file mode 100644 index 0000000000..5c21c8ab25 --- /dev/null +++ b/src/nm-device-generic.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_GENERIC_H +#define NM_DEVICE_GENERIC_H + +#include + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_GENERIC (nm_device_generic_get_type ()) +#define NM_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGeneric)) +#define NM_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) +#define NM_IS_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GENERIC)) +#define NM_IS_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GENERIC)) +#define NM_DEVICE_GENERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) + +typedef enum +{ + NM_DEVICE_GENERIC_ERROR_CONNECTION_NOT_GENERIC = 0, /*< nick=ConnectionNotGeneric >*/ + NM_DEVICE_GENERIC_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ + NM_DEVICE_GENERIC_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ +} NMDeviceGenericError; + +#define NM_DEVICE_GENERIC_HW_ADDRESS "hw-address" + +typedef struct { + NMDevice parent; +} NMDeviceGeneric; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*properties_changed) (NMDeviceGeneric *device, GHashTable *properties); +} NMDeviceGenericClass; + +GType nm_device_generic_get_type (void); + +NMDevice *nm_device_generic_new (const char *udi, + const char *iface, + const char *driver); + +G_END_DECLS + +#endif /* NM_DEVICE_GENERIC_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index a82d741ade..ef43496efa 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -50,6 +50,7 @@ #include "nm-device-bridge.h" #include "nm-device-vlan.h" #include "nm-device-adsl.h" +#include "nm-device-generic.h" #include "nm-system.h" #include "nm-properties-changed-signal.h" #include "nm-setting-bluetooth.h" @@ -2192,7 +2193,6 @@ udev_device_added_cb (NMUdevManager *udev_mgr, g_return_if_fail (udev_device != NULL); g_return_if_fail (iface != NULL); g_return_if_fail (sysfs_path != NULL); - g_return_if_fail (driver != NULL); /* Most devices will have an ifindex here */ if (ifindex > 0) { @@ -2232,6 +2232,9 @@ udev_device_added_cb (NMUdevManager *udev_mgr, } } + if (device == NULL && driver == NULL) + device = nm_device_generic_new (sysfs_path, iface, driver); + if (device == NULL) { if (is_olpc_mesh (udev_device)) /* must be before is_wireless */ device = nm_device_olpc_mesh_new (sysfs_path, iface, driver); @@ -2267,10 +2270,25 @@ udev_device_added_cb (NMUdevManager *udev_mgr, } } else nm_log_err (LOGD_HW, "(%s): failed to get VLAN parent ifindex", iface); - } else if (is_adsl (udev_device)) + } else if (is_adsl (udev_device)) { device = nm_device_adsl_new (sysfs_path, iface, driver); - else - device = nm_device_ethernet_new (sysfs_path, iface, driver); + } else { + gint etype; + gboolean is_ctc; + + /* For anything else, if it uses Ethernet encapsulation, consider it + * an Ethernet device. (But some s390 CTC-type devices report 256 for + * some reason, and we need to call them Ethernet too. FIXME: use + * something other than interface name to detect CTC here.) + */ + etype = g_udev_device_get_sysfs_attr_as_int (udev_device, "type"); + is_ctc = g_str_has_prefix (iface, "ctc") && (etype == 256); + + if (etype == ARPHRD_ETHER || is_ctc) + device = nm_device_ethernet_new (sysfs_path, iface, driver); + else + device = nm_device_generic_new (sysfs_path, iface, driver); + } } if (device) diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index a485349589..38b67a2ffb 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -353,7 +353,6 @@ dev_get_attrs (GUdevDevice *udev_device, GUdevDevice *parent = NULL, *grandparent = NULL; const char *ifname, *driver, *path, *subsys; gint ifindex = -1; - gboolean success = FALSE; g_return_val_if_fail (udev_device != NULL, FALSE); g_return_val_if_fail (out_ifname != NULL, FALSE); @@ -414,36 +413,27 @@ dev_get_attrs (GUdevDevice *udev_device, driver = "easytether"; break; } - - if (!driver) { - nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path); - goto out; - } } *out_ifname = ifname; *out_path = path; *out_driver = g_strdup (driver); *out_ifindex = ifindex; - success = TRUE; -out: if (grandparent) g_object_unref (grandparent); if (parent) g_object_unref (parent); - return success; + return TRUE; } static void net_add (NMUdevManager *self, GUdevDevice *udev_device) { gint ifindex = -1; - gint etype; const char *ifname = NULL, *path = NULL, *tmp; char *driver = NULL; - gboolean is_ctc; g_return_if_fail (udev_device != NULL); @@ -455,18 +445,6 @@ net_add (NMUdevManager *self, GUdevDevice *udev_device) goto out; } - etype = g_udev_device_get_sysfs_attr_as_int (udev_device, "type"); - is_ctc = (strncmp (ifname, "ctc", 3) == 0) && (etype == 256); - - /* Ignore devices that don't report Ethernet encapsulation, except for - * s390 CTC-type devices that report 256 for some reason. - * FIXME: use something other than interface name to detect CTC here. - */ - if ((etype != ARPHRD_ETHER) && (etype != ARPHRD_INFINIBAND) && (is_ctc == FALSE)) { - nm_log_dbg (LOGD_HW, "(%s): ignoring interface with type %d", ifname, etype); - goto out; - } - /* Not all ethernet devices are immediately usable; newer mobile broadband * devices (Ericsson, Option, Sierra) require setup on the tty before the * ethernet device is usable. 2.6.33 and later kernels set the 'DEVTYPE'