summaryrefslogtreecommitdiff
path: root/libnm-glib/nm-device.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-glib/nm-device.c')
-rw-r--r--libnm-glib/nm-device.c786
1 files changed, 715 insertions, 71 deletions
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
index 1c4fd7367..b328ba3bb 100644
--- a/libnm-glib/nm-device.c
+++ b/libnm-glib/nm-device.c
@@ -23,6 +23,7 @@
#include <string.h>
+#include <glib/gi18n.h>
#include <gudev/gudev.h>
#include "NetworkManager.h"
@@ -35,17 +36,20 @@
#include "nm-device-wimax.h"
#include "nm-device-infiniband.h"
#include "nm-device-bond.h"
+#include "nm-device-team.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"
#include "nm-object-cache.h"
#include "nm-remote-connection.h"
#include "nm-types.h"
-#include "nm-glib-marshal.h"
#include "nm-dbus-glib-types.h"
#include "nm-glib-compat.h"
+#include "nm-utils.h"
+#include "nm-dbus-helpers-private.h"
static GType _nm_device_type_for_path (DBusGConnection *connection,
const char *path);
@@ -53,6 +57,7 @@ static void _nm_device_type_for_path_async (DBusGConnection *connection,
const char *path,
NMObjectTypeCallbackFunc callback,
gpointer user_data);
+gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error);
G_DEFINE_TYPE_WITH_CODE (NMDevice, nm_device, NM_TYPE_OBJECT,
_nm_object_register_type_func (g_define_type_id, _nm_device_type_for_path,
@@ -73,6 +78,7 @@ typedef struct {
char *driver;
char *driver_version;
char *firmware_version;
+ char *type_description;
NMDeviceCapabilities capabilities;
gboolean managed;
gboolean firmware_missing;
@@ -89,8 +95,12 @@ typedef struct {
GPtrArray *available_connections;
GUdevClient *client;
- char *product;
- char *vendor;
+ char *product, *short_product;
+ char *vendor, *short_vendor;
+ char *description, *bus_name;
+
+ char *physical_port_id;
+ guint32 mtu;
} NMDevicePrivate;
enum {
@@ -116,6 +126,8 @@ enum {
PROP_DEVICE_TYPE,
PROP_ACTIVE_CONNECTION,
PROP_AVAILABLE_CONNECTIONS,
+ PROP_PHYSICAL_PORT_ID,
+ PROP_MTU,
LAST_PROP
};
@@ -128,6 +140,24 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
+/**
+ * nm_device_error_quark:
+ *
+ * Registers an error quark for #NMDevice if necessary.
+ *
+ * Returns: the error quark used for #NMDevice errors.
+ *
+ * Since: 0.9.10
+ **/
+GQuark
+nm_device_error_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (G_UNLIKELY (quark == 0))
+ quark = g_quark_from_static_string ("nm-device-error-quark");
+ return quark;
+}
static void
nm_device_init (NMDevice *device)
@@ -178,6 +208,8 @@ register_properties (NMDevice *device)
{ NM_DEVICE_STATE_REASON, &priv->state, demarshal_state_reason },
{ NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NM_DEVICE_AVAILABLE_CONNECTIONS, &priv->available_connections, NULL, NM_TYPE_REMOTE_CONNECTION },
+ { NM_DEVICE_PHYSICAL_PORT_ID, &priv->physical_port_id },
+ { NM_DEVICE_MTU, &priv->mtu },
/* Properties that exist in D-Bus but that we don't track */
{ "ip4-address", NULL },
@@ -282,10 +314,14 @@ _nm_device_gtype_from_dtype (NMDeviceType dtype)
return NM_TYPE_DEVICE_INFINIBAND;
case NM_DEVICE_TYPE_BOND:
return NM_TYPE_DEVICE_BOND;
+ case NM_DEVICE_TYPE_TEAM:
+ return NM_TYPE_DEVICE_TEAM;
case NM_DEVICE_TYPE_BRIDGE:
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;
@@ -305,14 +341,11 @@ constructed (GObject *object)
/* Catch a subclass setting the wrong type */
g_warn_if_fail (G_OBJECT_TYPE (object) == _nm_device_gtype_from_dtype (priv->device_type));
- priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
- NM_DBUS_SERVICE,
- nm_object_get_path (NM_OBJECT (object)),
- NM_DBUS_INTERFACE_DEVICE);
+ priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE);
register_properties (NM_DEVICE (object));
- dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__UINT_UINT_UINT,
+ dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
G_TYPE_NONE,
G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
G_TYPE_INVALID);
@@ -365,7 +398,13 @@ finalize (GObject *object)
g_free (priv->driver_version);
g_free (priv->firmware_version);
g_free (priv->product);
+ g_free (priv->short_product);
g_free (priv->vendor);
+ g_free (priv->short_vendor);
+ g_free (priv->description);
+ g_free (priv->bus_name);
+ g_free (priv->type_description);
+ g_free (priv->physical_port_id);
G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
}
@@ -450,6 +489,12 @@ get_property (GObject *object,
case PROP_VENDOR:
g_value_set_string (value, nm_device_get_vendor (device));
break;
+ case PROP_PHYSICAL_PORT_ID:
+ g_value_set_string (value, nm_device_get_physical_port_id (device));
+ break;
+ case PROP_MTU:
+ g_value_set_uint (value, nm_device_get_mtu (device));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -496,6 +541,8 @@ nm_device_class_init (NMDeviceClass *device_class)
object_class->dispose = dispose;
object_class->finalize = finalize;
+ device_class->connection_compatible = connection_compatible;
+
/* properties */
/**
@@ -534,7 +581,7 @@ nm_device_class_init (NMDeviceClass *device_class)
(object_class, PROP_DEVICE_TYPE,
g_param_spec_uint (NM_DEVICE_DEVICE_TYPE,
"Device Type",
- "Numeric device type (ie ethernet, wifi, etc)",
+ "Numeric device type (ie Ethernet, Wi-Fi, etc)",
NM_DEVICE_TYPE_UNKNOWN, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
G_PARAM_READABLE));
/**
@@ -779,6 +826,37 @@ nm_device_class_init (NMDeviceClass *device_class)
NULL,
G_PARAM_READABLE));
+ /**
+ * NMDevice:physical-port-id:
+ *
+ * The physical port ID of the device. (See
+ * nm_device_get_physical_port_id().)
+ *
+ * Since: 0.9.10
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PHYSICAL_PORT_ID,
+ g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID,
+ "Physical Port ID",
+ "Physical port ID",
+ NULL,
+ G_PARAM_READABLE));
+
+ /**
+ * NMDevice:mtu:
+ *
+ * The MTU of the device.
+ *
+ * Since: 0.9.10
+ **/
+ g_object_class_install_property
+ (object_class, PROP_MTU,
+ g_param_spec_uint (NM_DEVICE_MTU,
+ "MTU",
+ "MTU",
+ 0, G_MAXUINT32, 1500,
+ G_PARAM_READABLE));
+
/* signals */
/**
@@ -795,8 +873,7 @@ nm_device_class_init (NMDeviceClass *device_class)
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMDeviceClass, state_changed),
- NULL, NULL,
- _nm_glib_marshal_VOID__UINT_UINT_UINT,
+ NULL, NULL, NULL,
G_TYPE_NONE, 3,
G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
}
@@ -830,27 +907,25 @@ _nm_device_type_for_path (DBusGConnection *connection,
{
DBusGProxy *proxy;
GError *err = NULL;
- GValue value = {0,};
+ GValue value = G_VALUE_INIT;
NMDeviceType nm_dtype;
- proxy = dbus_g_proxy_new_for_name (connection,
- NM_DBUS_SERVICE,
- path,
- "org.freedesktop.DBus.Properties");
+ proxy = _nm_dbus_new_proxy_for_connection (connection, path, "org.freedesktop.DBus.Properties");
if (!proxy) {
g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
return G_TYPE_INVALID;
}
if (!dbus_g_proxy_call (proxy,
- "Get", &err,
- G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
- G_TYPE_STRING, "DeviceType",
- G_TYPE_INVALID,
- G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
- g_object_unref (proxy);
+ "Get", &err,
+ G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
+ G_TYPE_STRING, "DeviceType",
+ G_TYPE_INVALID,
+ G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
g_warning ("Error in get_property: %s\n", err->message);
g_error_free (err);
+ g_object_unref (proxy);
+ return G_TYPE_INVALID;
}
g_object_unref (proxy);
@@ -935,8 +1010,7 @@ _nm_device_type_for_path_async (DBusGConnection *connection,
async_data->callback = callback;
async_data->user_data = user_data;
- proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, path,
- "org.freedesktop.DBus.Properties");
+ proxy = _nm_dbus_new_proxy_for_connection (connection, path, "org.freedesktop.DBus.Properties");
dbus_g_proxy_begin_call (proxy, "Get",
async_got_type, async_data, NULL,
G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
@@ -985,7 +1059,7 @@ nm_device_get_ip_iface (NMDevice *device)
* nm_device_get_device_type:
* @device: a #NMDevice
*
- * Returns the numeric type of the #NMDevice, ie ethernet, wifi, etc.
+ * Returns the numeric type of the #NMDevice, ie Ethernet, Wi-Fi, etc.
*
* Returns: the device type
**/
@@ -1071,6 +1145,65 @@ nm_device_get_firmware_version (NMDevice *device)
}
/**
+ * nm_device_get_type_description:
+ * @device: a #NMDevice
+ *
+ * Gets a (non-localized) description of the type of device that
+ * @device is.
+ *
+ * Returns: the type description of the device. This is the internal
+ * string used by the device, and must not be modified.
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_device_get_type_description (NMDevice *device)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+ const char *desc, *typename;
+
+ g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+ if (priv->type_description)
+ return priv->type_description;
+
+ if (NM_DEVICE_GET_CLASS (device)->get_type_description) {
+ desc = NM_DEVICE_GET_CLASS (device)->get_type_description (device);
+ if (desc)
+ return desc;
+ }
+
+ typename = G_OBJECT_TYPE_NAME (device);
+ if (g_str_has_prefix (typename, "NMDevice"))
+ typename += 8;
+ priv->type_description = g_ascii_strdown (typename, -1);
+
+ return priv->type_description;
+}
+
+/**
+ * nm_device_get_hw_address:
+ * @device: a #NMDevice
+ *
+ * Gets the current a hardware address (MAC) for the @device.
+ *
+ * Returns: the current MAC of the device, or %NULL.
+ * This is the internal string used by the device, and must not be modified.
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_device_get_hw_address (NMDevice *device)
+{
+ g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+ if (NM_DEVICE_GET_CLASS (device)->get_hw_address)
+ return NM_DEVICE_GET_CLASS (device)->get_hw_address (device);
+
+ return NULL;
+}
+
+/**
* nm_device_get_capabilities:
* @device: a #NMDevice
*
@@ -1131,7 +1264,7 @@ nm_device_get_autoconnect (NMDevice *device)
void
nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect)
{
- GValue value = {0,};
+ GValue value = G_VALUE_INIT;
g_return_if_fail (NM_IS_DEVICE (device));
@@ -1172,6 +1305,10 @@ nm_device_get_firmware_missing (NMDevice *device)
*
* Gets the current #NMIP4Config associated with the #NMDevice.
*
+ * Note that as of NetworkManager 0.9.10, you can alternatively use
+ * nm_active_connection_get_ip4_config(), which also works with VPN
+ * connections.
+ *
* Returns: (transfer none): the #NMIP4Config or %NULL if the device is not activated.
**/
NMIP4Config *
@@ -1189,6 +1326,10 @@ nm_device_get_ip4_config (NMDevice *device)
*
* Gets the current #NMDHCP4Config associated with the #NMDevice.
*
+ * Note that as of NetworkManager 0.9.10, you can alternatively use
+ * nm_active_connection_get_dhcp4_config(), which also works with VPN
+ * connections.
+ *
* Returns: (transfer none): the #NMDHCP4Config or %NULL if the device is not activated or not
* using DHCP.
**/
@@ -1207,6 +1348,10 @@ nm_device_get_dhcp4_config (NMDevice *device)
*
* Gets the current #NMIP6Config associated with the #NMDevice.
*
+ * Note that as of NetworkManager 0.9.10, you can alternatively use
+ * nm_active_connection_get_ip6_config(), which also works with VPN
+ * connections.
+ *
* Returns: (transfer none): the #NMIP6Config or %NULL if the device is not activated.
**/
NMIP6Config *
@@ -1224,6 +1369,10 @@ nm_device_get_ip6_config (NMDevice *device)
*
* Gets the current #NMDHCP6Config associated with the #NMDevice.
*
+ * Note that as of NetworkManager 0.9.10, you can alternatively use
+ * nm_active_connection_get_dhcp6_config(), which also works with VPN
+ * connections.
+ *
* Returns: (transfer none): the #NMDHCP6Config or %NULL if the device is not activated or not
* using DHCP.
**/
@@ -1314,33 +1463,6 @@ nm_device_get_available_connections (NMDevice *device)
return handle_ptr_array_return (NM_DEVICE_GET_PRIVATE (device)->available_connections);
}
-/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
-
-static int hex2num (char c)
-{
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- return -1;
-}
-
-static int hex2byte (const char *hex)
-{
- int a, b;
- a = hex2num(*hex++);
- if (a < 0)
- return -1;
- b = hex2num(*hex++);
- if (b < 0)
- return -1;
- return (a << 4) | b;
-}
-
-/* End from hostap */
-
static char *
get_decoded_property (GUdevDevice *device, const char *property)
{
@@ -1356,7 +1478,7 @@ get_decoded_property (GUdevDevice *device, const char *property)
n = unescaped = g_malloc0 (len + 1);
while (*p) {
if ((len >= 4) && (*p == '\\') && (*(p+1) == 'x')) {
- *n++ = (char) hex2byte (p + 2);
+ *n++ = (char) nm_utils_hex2byte (p + 2);
p += 4;
len -= 4;
} else {
@@ -1368,23 +1490,31 @@ get_decoded_property (GUdevDevice *device, const char *property)
return unescaped;
}
+static gboolean
+ensure_udev_client (NMDevice *device)
+{
+ static const char *const subsys[3] = { "net", "tty", NULL };
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+
+ if (!priv->client)
+ priv->client = g_udev_client_new (subsys);
+
+ return priv->client != NULL;
+}
+
static char *
_get_udev_property (NMDevice *device,
const char *enc_prop, /* ID_XXX_ENC */
const char *db_prop) /* ID_XXX_FROM_DATABASE */
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
- const char *subsys[3] = { "net", "tty", NULL };
GUdevDevice *udev_device = NULL, *tmpdev, *olddev;
const char *ifname;
guint32 count = 0;
char *enc_value = NULL, *db_value = NULL;
- if (!priv->client) {
- priv->client = g_udev_client_new (subsys);
- if (!priv->client)
- return NULL;
- }
+ if (!ensure_udev_client (device))
+ return NULL;
ifname = nm_device_get_iface (device);
if (!ifname)
@@ -1424,7 +1554,7 @@ _get_udev_property (NMDevice *device,
/* Balance the initial g_udev_client_query_by_subsystem_and_name() */
g_object_unref (udev_device);
- /* Prefer the the encoded value which comes directly from the device
+ /* Prefer the encoded value which comes directly from the device
* over the hwdata database value.
*/
if (enc_value) {
@@ -1487,6 +1617,479 @@ nm_device_get_vendor (NMDevice *device)
return priv->vendor;
}
+static const char * const ignored_words[] = {
+ "Semiconductor",
+ "Components",
+ "Corporation",
+ "Communications",
+ "Company",
+ "Corp.",
+ "Corp",
+ "Co.",
+ "Inc.",
+ "Inc",
+ "Incorporated",
+ "Ltd.",
+ "Limited.",
+ "Intel?",
+ "chipset",
+ "adapter",
+ "[hex]",
+ "NDIS",
+ "Module",
+ NULL
+};
+
+static const char * const ignored_phrases[] = {
+ "Multiprotocol MAC/baseband processor",
+ "Wireless LAN Controller",
+ "Wireless LAN Adapter",
+ "Wireless Adapter",
+ "Network Connection",
+ "Wireless Cardbus Adapter",
+ "Wireless CardBus Adapter",
+ "54 Mbps Wireless PC Card",
+ "Wireless PC Card",
+ "Wireless PC",
+ "PC Card with XJACK(r) Antenna",
+ "Wireless cardbus",
+ "Wireless LAN PC Card",
+ "Technology Group Ltd.",
+ "Communication S.p.A.",
+ "Business Mobile Networks BV",
+ "Mobile Broadband Minicard Composite Device",
+ "Mobile Communications AB",
+ "(PC-Suite Mode)",
+ NULL
+};
+
+static char *
+fixup_desc_string (const char *desc)
+{
+ char *p, *temp;
+ char **words, **item;
+ GString *str;
+ int i;
+
+ if (!desc)
+ return NULL;
+
+ p = temp = g_strdup (desc);
+ while (*p) {
+ if (*p == '_' || *p == ',')
+ *p = ' ';
+ p++;
+ }
+
+ /* Attempt to shorten ID by ignoring certain phrases */
+ for (i = 0; ignored_phrases[i]; i++) {
+ p = strstr (temp, ignored_phrases[i]);
+ if (p) {
+ guint32 ignored_len = strlen (ignored_phrases[i]);
+
+ memmove (p, p + ignored_len, strlen (p + ignored_len) + 1); /* +1 for the \0 */
+ }
+ }
+
+ /* Attempt to shorten ID by ignoring certain individual words */
+ words = g_strsplit (temp, " ", 0);
+ str = g_string_new_len (NULL, strlen (temp));
+ g_free (temp);
+
+ for (item = words; *item; item++) {
+ gboolean ignore = FALSE;
+
+ if (**item == '\0')
+ continue;
+
+ for (i = 0; ignored_words[i]; i++) {
+ if (!strcmp (*item, ignored_words[i])) {
+ ignore = TRUE;
+ break;
+ }
+ }
+
+ if (!ignore) {
+ if (str->len)
+ g_string_append_c (str, ' ');
+ g_string_append (str, *item);
+ }
+ }
+ g_strfreev (words);
+
+ temp = str->str;
+ g_string_free (str, FALSE);
+
+ return temp;
+}
+
+static void
+get_description (NMDevice *device)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+ const char *dev_product;
+ const char *dev_vendor;
+ char *pdown;
+ char *vdown;
+ GString *str;
+
+ dev_product = nm_device_get_product (device);
+ priv->short_product = fixup_desc_string (dev_product);
+
+ dev_vendor = nm_device_get_vendor (device);
+ priv->short_vendor = fixup_desc_string (dev_vendor);
+
+ if (!dev_product || !dev_vendor) {
+ priv->description = g_strdup (nm_device_get_iface (device));
+ return;
+ }
+
+ str = g_string_new_len (NULL, strlen (priv->short_vendor) + strlen (priv->short_product) + 1);
+
+ /* Another quick hack; if all of the fixed up vendor string
+ * is found in product, ignore the vendor.
+ */
+ pdown = g_ascii_strdown (priv->short_product, -1);
+ vdown = g_ascii_strdown (priv->short_vendor, -1);
+ if (!strstr (pdown, vdown)) {
+ g_string_append (str, priv->short_vendor);
+ g_string_append_c (str, ' ');
+ }
+ g_free (pdown);
+ g_free (vdown);
+
+ g_string_append (str, priv->short_product);
+
+ priv->description = g_string_free (str, FALSE);
+}
+
+static const char *
+get_short_vendor (NMDevice *device)
+{
+ NMDevicePrivate *priv;
+
+ g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+ priv = NM_DEVICE_GET_PRIVATE (device);
+
+ if (!priv->description)
+ get_description (device);
+
+ return priv->short_vendor;
+}
+
+/**
+ * nm_device_get_description:
+ * @device: an #NMDevice
+ *
+ * Gets a description of @device, incorporating the results of
+ * nm_device_get_short_vendor() and nm_device_get_short_product().
+ *
+ * Returns: a description of @device. If either the vendor or the
+ * product name is unknown, this returns the interface name.
+ *
+ * Since: 0.9.10
+ */
+const char *
+nm_device_get_description (NMDevice *device)
+{
+ NMDevicePrivate *priv;
+
+ g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+ priv = NM_DEVICE_GET_PRIVATE (device);
+
+ if (!priv->description)
+ get_description (device);
+
+ return priv->description;
+}
+
+static const char *
+get_type_name (NMDevice *device)
+{
+ switch (nm_device_get_device_type (device)) {
+ case NM_DEVICE_TYPE_ETHERNET:
+ return _("Ethernet");
+ case NM_DEVICE_TYPE_WIFI:
+ return _("Wi-Fi");
+ case NM_DEVICE_TYPE_BT:
+ return _("Bluetooth");
+ case NM_DEVICE_TYPE_OLPC_MESH:
+ return _("OLPC Mesh");
+ case NM_DEVICE_TYPE_WIMAX:
+ return _("WiMAX");
+ case NM_DEVICE_TYPE_MODEM:
+ return _("Mobile Broadband");
+ case NM_DEVICE_TYPE_INFINIBAND:
+ return _("InfiniBand");
+ case NM_DEVICE_TYPE_BOND:
+ return _("Bond");
+ case NM_DEVICE_TYPE_TEAM:
+ return _("Team");
+ case NM_DEVICE_TYPE_BRIDGE:
+ return _("Bridge");
+ case NM_DEVICE_TYPE_VLAN:
+ return _("VLAN");
+ case NM_DEVICE_TYPE_ADSL:
+ return _("ADSL");
+ default:
+ return _("Unknown");
+ }
+}
+
+static char *
+get_device_type_name_with_iface (NMDevice *device)
+{
+ const char *type_name = get_type_name (device);
+
+ switch (nm_device_get_device_type (device)) {
+ case NM_DEVICE_TYPE_BOND:
+ case NM_DEVICE_TYPE_TEAM:
+ case NM_DEVICE_TYPE_BRIDGE:
+ case NM_DEVICE_TYPE_VLAN:
+ return g_strdup_printf ("%s (%s)", type_name, nm_device_get_iface (device));
+ default:
+ return g_strdup (type_name);
+ }
+}
+
+static char *
+get_device_generic_type_name_with_iface (NMDevice *device)
+{
+ switch (nm_device_get_device_type (device)) {
+ case NM_DEVICE_TYPE_ETHERNET:
+ case NM_DEVICE_TYPE_INFINIBAND:
+ return g_strdup (_("Wired"));
+ default:
+ return get_device_type_name_with_iface (device);
+ }
+}
+
+static const char *
+get_bus_name (NMDevice *device)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+ GUdevDevice *udevice;
+ const char *ifname, *bus;
+
+ if (priv->bus_name)
+ goto out;
+
+ if (!ensure_udev_client (device))
+ return NULL;
+
+ ifname = nm_device_get_iface (device);
+ if (!ifname)
+ return NULL;
+
+ udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname);
+ if (!udevice)
+ udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname);
+ if (!udevice)
+ return NULL;
+
+ bus = g_udev_device_get_property (udevice, "ID_BUS");
+ if (!g_strcmp0 (bus, "pci"))
+ priv->bus_name = g_strdup (_("PCI"));
+ else if (!g_strcmp0 (bus, "usb"))
+ priv->bus_name = g_strdup (_("USB"));
+ else {
+ /* Use "" instead of NULL so we can tell later that we've
+ * already tried.
+ */
+ priv->bus_name = g_strdup ("");
+ }
+
+out:
+ if (*priv->bus_name)
+ return priv->bus_name;
+ else
+ return NULL;
+}
+
+static gboolean
+find_duplicates (char **names,
+ gboolean *duplicates,
+ int num_devices)
+{
+ int i, j;
+ gboolean found_any = FALSE;
+
+ memset (duplicates, 0, num_devices * sizeof (gboolean));
+ for (i = 0; i < num_devices; i++) {
+ if (duplicates[i])
+ continue;
+ for (j = i + 1; j < num_devices; j++) {
+ if (duplicates[j])
+ continue;
+ if (!strcmp (names[i], names[j]))
+ duplicates[i] = duplicates[j] = found_any = TRUE;
+ }
+ }
+
+ return found_any;
+}
+
+/**
+ * nm_device_disambiguate_names:
+ * @devices: (array length=num_devices): an array of #NMDevice
+ * @num_devices: length of @devices
+ *
+ * Generates a list of short-ish unique presentation names for the
+ * devices in @devices.
+ *
+ * Returns: (transfer full) (array zero-terminated=1): the device names
+ *
+ * Since: 0.9.10
+ */
+char **
+nm_device_disambiguate_names (NMDevice **devices,
+ int num_devices)
+{
+ char **names;
+ gboolean *duplicates;
+ int i;
+
+ names = g_new (char *, num_devices + 1);
+ duplicates = g_new (gboolean, num_devices);
+
+ /* Generic device name */
+ for (i = 0; i < num_devices; i++)
+ names[i] = get_device_generic_type_name_with_iface (devices[i]);
+ if (!find_duplicates (names, duplicates, num_devices))
+ goto done;
+
+ /* Try specific names (eg, "Ethernet" and "InfiniBand" rather
+ * than "Wired")
+ */
+ for (i = 0; i < num_devices; i++) {
+ if (duplicates[i]) {
+ g_free (names[i]);
+ names[i] = get_device_type_name_with_iface (devices[i]);
+ }
+ }
+ if (!find_duplicates (names, duplicates, num_devices))
+ goto done;
+
+ /* Try prefixing bus name (eg, "PCI Ethernet" vs "USB Ethernet") */
+ for (i = 0; i < num_devices; i++) {
+ if (duplicates[i]) {
+ const char *bus = get_bus_name (devices[i]);
+ char *name;
+
+ if (!bus)
+ continue;
+
+ g_free (names[i]);
+ name = get_device_type_name_with_iface (devices[i]);
+ /* Translators: the first %s is a bus name (eg, "USB") or
+ * product name, the second is a device type (eg,
+ * "Ethernet"). You can change this to something like
+ * "%2$s (%1$s)" if there's no grammatical way to combine
+ * the strings otherwise.
+ */
+ names[i] = g_strdup_printf (C_("long device name", "%s %s"),
+ bus, name);
+ g_free (name);
+ }
+ }
+ if (!find_duplicates (names, duplicates, num_devices))
+ goto done;
+
+ /* Try prefixing vendor name */
+ for (i = 0; i < num_devices; i++) {
+ if (duplicates[i]) {
+ const char *vendor = get_short_vendor (devices[i]);
+ char *name;
+
+ if (!vendor)
+ continue;
+
+ g_free (names[i]);
+ name = get_device_type_name_with_iface (devices[i]);
+ names[i] = g_strdup_printf (C_("long device name", "%s %s"),
+ vendor,
+ get_type_name (devices[i]));
+ g_free (name);
+ }
+ }
+ if (!find_duplicates (names, duplicates, num_devices))
+ goto done;
+
+ /* We have multiple identical network cards, so we have to differentiate
+ * them by interface name.
+ */
+ for (i = 0; i < num_devices; i++) {
+ if (duplicates[i]) {
+ const char *interface = nm_device_get_iface (devices[i]);
+
+ if (!interface)
+ continue;
+
+ g_free (names[i]);
+ names[i] = g_strdup_printf ("%s (%s)",
+ get_type_name (devices[i]),
+ interface);
+ }
+ }
+
+done:
+ g_free (duplicates);
+ names[num_devices] = NULL;
+ return names;
+}
+
+/**
+ * nm_device_get_physical_port_id:
+ * @device: a #NMDevice
+ *
+ * Gets the physical port ID of the #NMDevice. If non-%NULL, this is
+ * an opaque string that can be used to recognize when
+ * seemingly-unrelated #NMDevices are actually just different virtual
+ * ports on a single physical port. (Eg, NPAR / SR-IOV.)
+ *
+ * Returns: the physical port ID of the device, or %NULL if the port
+ * ID is unknown. This is the internal string used by the device and
+ * must not be modified.
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_device_get_physical_port_id (NMDevice *device)
+{
+ NMDevicePrivate *priv;
+
+ g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+ priv = NM_DEVICE_GET_PRIVATE (device);
+
+ _nm_object_ensure_inited (NM_OBJECT (device));
+ if (priv->physical_port_id && *priv->physical_port_id)
+ return priv->physical_port_id;
+ else
+ return NULL;
+}
+
+/**
+ * nm_device_get_mtu:
+ * @device: a #NMDevice
+ *
+ * Gets the MTU of the #NMDevice.
+ *
+ * Returns: the MTU of the device.
+ *
+ * Since: 0.9.10
+ **/
+guint32
+nm_device_get_mtu (NMDevice *device)
+{
+ g_return_val_if_fail (NM_IS_DEVICE (device), 0);
+
+ _nm_object_ensure_inited (NM_OBJECT (device));
+ return NM_DEVICE_GET_PRIVATE (device)->mtu;
+}
+
typedef struct {
NMDevice *device;
NMDeviceDeactivateFn fn;
@@ -1555,8 +2158,8 @@ nm_device_disconnect (NMDevice *device,
*
* Validates a given connection for a given #NMDevice object and returns
* whether the connection may be activated with the device. For example if
- * @device is a WiFi device that supports only WEP encryption, the connection
- * will only be valid if it is a WiFi connection which describes a WEP or open
+ * @device is a Wi-Fi device that supports only WEP encryption, the connection
+ * will only be valid if it is a Wi-Fi connection which describes a WEP or open
* network, and will not be valid if it describes a WPA network, or if it is
* an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
* device.
@@ -1570,6 +2173,26 @@ nm_device_connection_valid (NMDevice *device, NMConnection *connection)
return nm_device_connection_compatible (device, connection, NULL);
}
+gboolean
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+{
+ NMSettingConnection *s_con;
+ const char *config_iface, *device_iface;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+
+ config_iface = nm_setting_connection_get_interface_name (s_con);
+ device_iface = nm_device_get_iface (device);
+ if (config_iface && g_strcmp0 (config_iface, device_iface) != 0) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INTERFACE_MISMATCH,
+ "The interface names of the device and the connection didn't match.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
* nm_device_connection_compatible:
* @device: an #NMDevice to validate @connection against
@@ -1578,8 +2201,8 @@ nm_device_connection_valid (NMDevice *device, NMConnection *connection)
*
* Validates a given connection for a given #NMDevice object and returns
* whether the connection may be activated with the device. For example if
- * @device is a WiFi device that supports only WEP encryption, the connection
- * will only be valid if it is a WiFi connection which describes a WEP or open
+ * @device is a Wi-Fi device that supports only WEP encryption, the connection
+ * will only be valid if it is a Wi-Fi connection which describes a WEP or open
* network, and will not be valid if it describes a WPA network, or if it is
* an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
* device.
@@ -1594,9 +2217,11 @@ nm_device_connection_valid (NMDevice *device, NMConnection *connection)
gboolean
nm_device_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
- if (NM_DEVICE_GET_CLASS (device)->connection_compatible)
- return NM_DEVICE_GET_CLASS (device)->connection_compatible (device, connection, error);
- return FALSE;
+ g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ return NM_DEVICE_GET_CLASS (device)->connection_compatible (device, connection, error);
}
/**
@@ -1606,10 +2231,10 @@ nm_device_connection_compatible (NMDevice *device, NMConnection *connection, GEr
*
* Filters a given list of connections for a given #NMDevice object and return
* connections which may be activated with the device. For example if @device
- * is a WiFi device that supports only WEP encryption, the returned list will
- * contain any WiFi connections in @connections that allow connection to
+ * is a Wi-Fi device that supports only WEP encryption, the returned list will
+ * contain any Wi-Fi connections in @connections that allow connection to
* unencrypted or WEP-enabled SSIDs. The returned list will not contain
- * Ethernet, Bluetooth, WiFi WPA connections, or any other connection that is
+ * Ethernet, Bluetooth, Wi-Fi WPA connections, or any other connection that is
* incompatible with the device. To get the full list of connections see
* nm_remote_settings_list_connections().
*
@@ -1636,3 +2261,22 @@ nm_device_filter_connections (NMDevice *device, const GSList *connections)
return g_slist_reverse (filtered);
}
+/**
+ * nm_device_get_setting_type:
+ * @device: an #NMDevice
+ *
+ * Gets the (primary) #NMSetting subtype associated with connections
+ * that can be used on @device.
+ *
+ * Returns: @device's associated #NMSetting type
+ *
+ * Since: 0.9.10
+ */
+GType
+nm_device_get_setting_type (NMDevice *device)
+{
+ g_return_val_if_fail (NM_IS_DEVICE (device), G_TYPE_INVALID);
+ g_return_val_if_fail (NM_DEVICE_GET_CLASS (device)->get_setting_type != NULL, G_TYPE_INVALID);
+
+ return NM_DEVICE_GET_CLASS (device)->get_setting_type (device);
+}