diff options
-rw-r--r-- | libnm-glib/libnm-glib.ver | 2 | ||||
-rw-r--r-- | libnm-glib/nm-device.c | 453 | ||||
-rw-r--r-- | libnm-glib/nm-device.h | 8 | ||||
-rw-r--r-- | libnm-util/libnm-util.ver | 1 | ||||
-rw-r--r-- | libnm-util/nm-connection.c | 42 | ||||
-rw-r--r-- | libnm-util/nm-connection.h | 6 | ||||
-rw-r--r-- | po/POTFILES.in | 2 |
7 files changed, 502 insertions, 12 deletions
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 9f0db93b23..ca47f9163b 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -102,6 +102,7 @@ global: nm_device_bt_new; nm_device_connection_compatible; nm_device_connection_valid; + nm_device_disambiguate_names; nm_device_disconnect; nm_device_error_get_type; nm_device_error_quark; @@ -123,6 +124,7 @@ global: nm_device_get_autoconnect; nm_device_get_available_connections; nm_device_get_capabilities; + nm_device_get_description; nm_device_get_device_type; nm_device_get_dhcp4_config; nm_device_get_dhcp6_config; diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 806c9347d3..a8d66052a3 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" @@ -94,8 +95,9 @@ 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; @@ -394,7 +396,11 @@ 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); @@ -1481,23 +1487,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) @@ -1600,6 +1614,429 @@ 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 diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h index 33ab8a3dcb..3f38cf64c3 100644 --- a/libnm-glib/nm-device.h +++ b/libnm-glib/nm-device.h @@ -136,11 +136,15 @@ NMDeviceState nm_device_get_state (NMDevice *device); NMDeviceState nm_device_get_state_reason (NMDevice *device, NMDeviceStateReason *reason); NMActiveConnection * nm_device_get_active_connection(NMDevice *device); const GPtrArray * nm_device_get_available_connections(NMDevice *device); -const char * nm_device_get_product (NMDevice *device); -const char * nm_device_get_vendor (NMDevice *device); const char * nm_device_get_physical_port_id (NMDevice *device); guint32 nm_device_get_mtu (NMDevice *device); +const char * nm_device_get_product (NMDevice *device); +const char * nm_device_get_vendor (NMDevice *device); +const char * nm_device_get_description (NMDevice *device); +char ** nm_device_disambiguate_names (NMDevice **devices, + int num_devices); + typedef void (*NMDeviceDeactivateFn) (NMDevice *device, GError *error, gpointer user_data); void nm_device_disconnect (NMDevice *device, diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver index 3797e2beae..60614d2e4a 100644 --- a/libnm-util/libnm-util.ver +++ b/libnm-util/libnm-util.ver @@ -43,6 +43,7 @@ global: nm_connection_get_setting_wireless_security; nm_connection_get_type; nm_connection_get_uuid; + nm_connection_get_virtual_device_description; nm_connection_get_virtual_iface_name; nm_connection_is_type; nm_connection_lookup_setting_type; diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c index f7d643193c..52b541120b 100644 --- a/libnm-util/nm-connection.c +++ b/libnm-util/nm-connection.c @@ -24,6 +24,7 @@ */ #include <glib-object.h> +#include <glib/gi18n.h> #include <dbus/dbus-glib.h> #include <string.h> #include "nm-connection.h" @@ -1242,6 +1243,47 @@ nm_connection_get_id (NMConnection *connection) return nm_setting_connection_get_id (s_con); } +/** + * nm_connection_get_virtual_device_description: + * @connection: an #NMConnection for a virtual device type + * + * Returns the name that nm_device_disambiguate_names() would + * return for the virtual device that would be created for @connection. + * Eg, "VLAN (eth1.1)". + * + * Returns: (transfer full): the name of @connection's device, + * or %NULL if @connection is not a virtual connection type + */ +char * +nm_connection_get_virtual_device_description (NMConnection *connection) +{ + const char *iface, *type, *display_type; + NMSettingConnection *s_con; + + iface = nm_connection_get_virtual_iface_name (connection); + if (!iface) + return NULL; + + s_con = nm_connection_get_setting_connection (connection); + g_return_val_if_fail (s_con != NULL, NULL); + type = nm_setting_connection_get_connection_type (s_con); + + if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) + display_type = _("Bond"); + else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME)) + display_type = _("Team"); + else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)) + display_type = _("Bridge"); + else if (!strcmp (type, NM_SETTING_VLAN_SETTING_NAME)) + display_type = _("VLAN"); + else { + g_warning ("Unrecognized virtual device type '%s'", type); + display_type = type; + } + + return g_strdup_printf ("%s (%s)", display_type, iface); +} + /*************************************************************/ /** diff --git a/libnm-util/nm-connection.h b/libnm-util/nm-connection.h index cda8391e8b..79f6504313 100644 --- a/libnm-util/nm-connection.h +++ b/libnm-util/nm-connection.h @@ -196,9 +196,11 @@ GType nm_connection_lookup_setting_type (const char *name); GType nm_connection_lookup_setting_type_by_quark (GQuark error_quark); /* Helpers */ -const char * nm_connection_get_uuid (NMConnection *connection); +const char * nm_connection_get_uuid (NMConnection *connection); -const char * nm_connection_get_id (NMConnection *connection); +const char * nm_connection_get_id (NMConnection *connection); + +char * nm_connection_get_virtual_device_description (NMConnection *connection); NMSetting8021x * nm_connection_get_setting_802_1x (NMConnection *connection); NMSettingBluetooth * nm_connection_get_setting_bluetooth (NMConnection *connection); diff --git a/po/POTFILES.in b/po/POTFILES.in index c365014f22..b530426a4c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -8,9 +8,11 @@ cli/src/network-manager.c cli/src/nmcli.c cli/src/settings.c cli/src/utils.c +libnm-glib/nm-device.c libnm-util/crypto.c libnm-util/crypto_gnutls.c libnm-util/crypto_nss.c +libnm-util/nm-connection.c libnm-util/nm-setting-8021x.c libnm-util/nm-setting-adsl.c libnm-util/nm-setting-bluetooth.c |