initial IPoIB patches



This only implements the basics (ie, NMSettingInfiniband doesn't have
very many properties yet), but it does work for basic IPoIB setups.

Re: the discussion in TODO about merging vs splitting with the
wired/ethernet code, it seemed to make more sense to split; most of the
ethernet-related properties don't apply to infiniband connections (in
particular, you can't do MAC address cloning, and of course all the s390
stuff is superfluous), and infiniband will eventually have several of
its own properties, and so if we tried to merge them together, you'd end
up with this weird bimodal NMSettingWired class. So, I made
NMSettingInfiniband.

On the daemon side, it also didn't make sense to merge them, but there
was a lot more shared code there than on the settings side. So I split
an NMDeviceWired out of NMDeviceEthernet, and then made NMDeviceEthernet
and NMDeviceInfiniband inherit from that. NMDeviceWired isn't visible to
the D-Bus interfaces though, and so libnm-glib gets a
NMDeviceInfiniband, but not an NMDeviceWired.

This is slightly awkward in that now we have both NMSettingWired and
NMDeviceWired, which don't mean the same thing. It might make sense to
rename NMSettingWired to NMSettingEthernet?

There will be more patches later, but I wanted to get the NMDeviceWired
split in now (assuming we are going to go with that rather than some
other solution) to avoid rebasing pain later.
>From b8ef43bd8d456616ff9eeb9d3ecd73bc047c4d81 Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Fri, 21 Oct 2011 16:13:14 -0400
Subject: [PATCH 1/7] Three small obvious fixes

---
 cli/src/devices.c        |    2 +-
 include/NetworkManager.h |    3 ++-
 src/nm-device-ethernet.c |    2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/cli/src/devices.c b/cli/src/devices.c
index 500d234..0b19edb 100644
--- a/cli/src/devices.c
+++ b/cli/src/devices.c
@@ -645,7 +645,7 @@ show_device_info (gpointer data, gpointer user_data)
 			nmc->allowed_fields[1].value = nm_device_get_iface (device);
 			nmc->allowed_fields[2].value = device_type_to_string (device);
 			nmc->allowed_fields[3].value = nm_device_get_driver (device) ? nm_device_get_driver (device) : _("(unknown)");
-			nmc->allowed_fields[4].value = hwaddr ? hwaddr : _("unknown)");
+			nmc->allowed_fields[4].value = hwaddr ? hwaddr : _("(unknown)");
 			nmc->allowed_fields[5].value = device_state_to_string (state);
 
 			nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX;
diff --git a/include/NetworkManager.h b/include/NetworkManager.h
index 3522dd2..0a00135 100644
--- a/include/NetworkManager.h
+++ b/include/NetworkManager.h
@@ -102,7 +102,8 @@ typedef enum {
  * @NM_DEVICE_TYPE_MODEM: a modem supporting analog telephone, CDMA/EVDO,
  * GSM/UMTS, or LTE network access protocols
  *
- * #NMState values indicate the current overall networking state.
+ * #NMDeviceType values indicate the type of hardware represented by
+ * an #NMDevice.
  **/
 typedef enum {
 	NM_DEVICE_TYPE_UNKNOWN   = 0,
diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c
index 8556c5b..f114642 100644
--- a/src/nm-device-ethernet.c
+++ b/src/nm-device-ethernet.c
@@ -412,7 +412,7 @@ constructor (GType type,
 	self = NM_DEVICE (object);
 	priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 
-	nm_log_dbg (LOGD_HW | LOGD_OLPC_MESH, "(%s): kernel ifindex %d",
+	nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): kernel ifindex %d",
 	            nm_device_get_iface (NM_DEVICE (self)),
 	            nm_device_get_ifindex (NM_DEVICE (self)));
 
-- 
1.7.7

>From cebaa47809b33e264302e1501d703100b80cc234 Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Mon, 10 Oct 2011 16:00:28 -0400
Subject: [PATCH 2/7] libnm-util: add ether_ntoa/ether_aton-like utility
 methods

nm_utils_hwaddr_ntoa() and nm_utils_hwaddr_aton() are like
ether_ntoa()/ether_aton(), but handle IPoIB too.

nm_utils_hwaddr_atoba() is like _aton() but returns a GByteArray,
since that's what's wanted in many places.

Also remove nm_ether_ntop() and replace uses of it with
nm_utils_hwaddr_ntoa().
---
 libnm-util/libnm-util.ver                      |    4 +
 libnm-util/nm-utils.c                          |  114 ++++++++++++++++++++++++
 libnm-util/nm-utils.h                          |   14 +++
 src/NetworkManagerUtils.c                      |   12 ---
 src/NetworkManagerUtils.h                      |    2 -
 src/nm-device-ethernet.c                       |    7 +-
 src/nm-device-olpc-mesh.c                      |    2 +-
 src/nm-device-wifi.c                           |   10 +-
 src/nm-wifi-ap.c                               |    3 +-
 src/settings/nm-settings-connection.c          |    2 +-
 src/settings/plugins/ifcfg-rh/reader.c         |   14 +--
 src/settings/plugins/ifnet/connection_parser.c |   18 ++---
 src/settings/plugins/ifupdown/plugin.c         |    6 +-
 src/settings/plugins/keyfile/reader.c          |    8 +-
 src/wimax/nm-device-wimax.c                    |    2 +-
 15 files changed, 160 insertions(+), 58 deletions(-)

diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index 53c2482..07122de 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -423,6 +423,10 @@ global:
 	nm_utils_deinit;
 	nm_utils_escape_ssid;
 	nm_utils_gvalue_hash_dup;
+	nm_utils_hwaddr_atoba;
+	nm_utils_hwaddr_aton;
+	nm_utils_hwaddr_len;
+	nm_utils_hwaddr_ntoa;
 	nm_utils_init;
 	nm_utils_ip4_addresses_from_gvalue;
 	nm_utils_ip4_addresses_to_gvalue;
diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c
index 9d4418e..3df66a0 100644
--- a/libnm-util/nm-utils.c
+++ b/libnm-util/nm-utils.c
@@ -25,11 +25,14 @@
  */
 
 #include "config.h"
+#include <ctype.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <arpa/inet.h>
+#include <netinet/ether.h>
+#include <linux/if_infiniband.h>
 
 #include "wireless-helper.h"
 
@@ -2386,3 +2389,114 @@ nm_utils_wifi_is_channel_valid (guint32 channel, const char *band)
 		return FALSE;
 }
 
+/**
+ * nm_utils_hwaddr_len:
+ * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
+ *
+ * Returns the length in octets of a hardware address of type @type.
+ *
+ * Return value: the length
+ */
+int
+nm_utils_hwaddr_len (int type)
+{
+	if (type == ARPHRD_ETHER)
+		return ETH_ALEN;
+	else if (type == ARPHRD_INFINIBAND)
+		return INFINIBAND_ALEN;
+	else
+		g_return_val_if_reached (-1);
+}
+
+#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
+
+/**
+ * nm_utils_hwaddr_aton:
+ * @asc: the ASCII representation of a hardware address
+ * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
+ * @buffer: buffer to store the result into
+ *
+ * Parses @asc and converts it to binary form in @buffer. See
+ * nm_utils_hwaddr_atoba() if you'd rather have the result in a
+ * #GByteArray.
+ *
+ * Return value: @buffer, or %NULL if @asc couldn't be parsed
+ */
+guint8 *
+nm_utils_hwaddr_aton (const char *asc, int type, gpointer buffer)
+{
+	const char *in = asc;
+	guint8 *out = (guint8 *)buffer;
+	int left = nm_utils_hwaddr_len (type);
+
+	while (left && *in) {
+		if (!isxdigit (in[0]) || !isxdigit (in[1]))
+			return NULL;
+
+		*out++ = (HEXVAL (in[0]) << 4) + HEXVAL (in[1]);
+		left--;
+		in += 2;
+		if (*in) {
+			if (*in != ':')
+				return NULL;
+			in++;
+		}
+	}
+
+	if (left == 0 && !*in)
+		return buffer;
+	else
+		return NULL;
+}
+
+/**
+ * nm_utils_hwaddr_atoba:
+ * @asc: the ASCII representation of a hardware address
+ * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
+ *
+ * Parses @asc and converts it to binary form in a #GByteArray. See
+ * nm_utils_hwaddr_aton() if you don't want a #GByteArray.
+ *
+ * Return value: a new #GByteArray, or %NULL if @asc couldn't be
+ * parsed
+ */
+GByteArray *
+nm_utils_hwaddr_atoba (const char *asc, int type)
+{
+	GByteArray *ba;
+	int len = nm_utils_hwaddr_len (type);
+
+	ba = g_byte_array_sized_new (len);
+	ba->len = len;
+	if (!nm_utils_hwaddr_aton (asc, type, ba->data)) {
+		g_byte_array_unref (ba);
+		return NULL;
+	}
+
+	return ba;
+}
+
+/**
+ * nm_utils_hwaddr_ntoa:
+ * @addr: a binary hardware address
+ * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
+ *
+ * Converts @addr to textual form.
+ *
+ * Return value: (transfer full): the textual form of @addr
+ */
+char *
+nm_utils_hwaddr_ntoa (gconstpointer addr, int type)
+{
+	const guint8 *in = addr;
+	GString *out = g_string_new (NULL);
+	int left = nm_utils_hwaddr_len (type);
+
+	while (left--) {
+		if (out->len)
+			g_string_append_c (out, ':');
+		g_string_append_printf (out, "%02X", *in++);
+	}
+
+	return g_string_free (out, FALSE);
+}
diff --git a/libnm-util/nm-utils.h b/libnm-util/nm-utils.h
index 6a17926..d858d3f 100644
--- a/libnm-util/nm-utils.h
+++ b/libnm-util/nm-utils.h
@@ -118,6 +118,20 @@ guint32 nm_utils_wifi_channel_to_freq (guint32 channel, const char *band);
 guint32 nm_utils_wifi_find_next_channel (guint32 channel, int direction, char *band);
 gboolean nm_utils_wifi_is_channel_valid (guint32 channel, const char *band);
 
+/**
+ * NM_UTILS_HWADDR_LEN_MAX:
+ *
+ * The maximum length of a hardware address of a type known by
+ * nm_utils_hwaddr_len() or nm_utils_hwaddr_aton(). This can be used
+ * as the size of the buffer passed to nm_utils_hwaddr_aton().
+ */
+#define NM_UTILS_HWADDR_LEN_MAX 20 /* INFINIBAND_ALEN */
+
+int         nm_utils_hwaddr_len   (int type) G_GNUC_PURE;
+char       *nm_utils_hwaddr_ntoa  (gconstpointer addr, int type);
+GByteArray *nm_utils_hwaddr_atoba (const char *asc, int type);
+guint8     *nm_utils_hwaddr_aton  (const char *asc, int type, gpointer buffer);
+
 G_END_DECLS
 
 #endif /* NM_UTILS_H */
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 451de6d..2e823b0 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -159,18 +159,6 @@ nm_utils_ip4_prefix_to_netmask (guint32 prefix)
 	return (guint32) htonl (netmask);
 }
 
-char *
-nm_ether_ntop (const struct ether_addr *mac)
-{
-	/* we like leading zeros and all-caps, instead
-	 * of what glibc's ether_ntop() gives us
-	 */
-	return g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
-	                        mac->ether_addr_octet[0], mac->ether_addr_octet[1],
-	                        mac->ether_addr_octet[2], mac->ether_addr_octet[3],
-	                        mac->ether_addr_octet[4], mac->ether_addr_octet[5]);
-}
-
 void
 nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting)
 {
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index 1bf741e..d3736c5 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -37,8 +37,6 @@ gboolean nm_ethernet_address_is_valid (const struct ether_addr *test_addr);
 
 int nm_spawn_process (const char *args);
 
-char *nm_ether_ntop (const struct ether_addr *mac);
-
 void nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting);
 void nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting);
 
diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c
index f114642..0d05dd4 100644
--- a/src/nm-device-ethernet.c
+++ b/src/nm-device-ethernet.c
@@ -60,6 +60,7 @@
 #include "nm-properties-changed-signal.h"
 #include "nm-dhcp-manager.h"
 #include "nm-netlink-utils.h"
+#include "nm-utils.h"
 
 #include "nm-device-ethernet-glue.h"
 
@@ -1764,7 +1765,7 @@ spec_match_list (NMDevice *device, const GSList *specs)
 	char *hwaddr;
 	gboolean matched;
 
-	hwaddr = nm_ether_ntop ((struct ether_addr *) &priv->perm_hw_addr);
+	hwaddr = nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER);
 	matched = nm_match_spec_hwaddr (specs, hwaddr);
 	g_free (hwaddr);
 
@@ -1950,10 +1951,10 @@ get_property (GObject *object, guint prop_id,
 
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
-		g_value_take_string (value, nm_ether_ntop ((struct ether_addr *) &priv->hw_addr));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->hw_addr, ARPHRD_ETHER));
 		break;
 	case PROP_PERM_HW_ADDRESS:
-		g_value_take_string (value, nm_ether_ntop ((struct ether_addr *) &priv->perm_hw_addr));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER));
 		break;
 	case PROP_SPEED:
 		g_value_set_uint (value, nm_device_ethernet_get_speed (self));
diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c
index ddd5198..2b5015f 100644
--- a/src/nm-device-olpc-mesh.c
+++ b/src/nm-device-olpc-mesh.c
@@ -672,7 +672,7 @@ get_property (GObject *object, guint prop_id,
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		nm_device_olpc_mesh_get_address (device, &hw_addr);
-		g_value_take_string (value, nm_ether_ntop (&hw_addr));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (&hw_addr, ARPHRD_ETHER));
 		break;
 	case PROP_COMPANION:
 		if (priv->companion)
diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c
index 9695c07..740f9f4 100644
--- a/src/nm-device-wifi.c
+++ b/src/nm-device-wifi.c
@@ -1073,13 +1073,13 @@ periodic_update (NMDeviceWifi *self)
 
 		if (new_ap) {
 			new_bssid = nm_ap_get_address (new_ap);
-			new_addr = nm_ether_ntop (new_bssid);
+			new_addr = nm_utils_hwaddr_ntoa (new_bssid, ARPHRD_ETHER);
 			new_ssid = nm_ap_get_ssid (new_ap);
 		}
 
 		if (priv->current_ap) {
 			old_bssid = nm_ap_get_address (priv->current_ap);
-			old_addr = nm_ether_ntop (old_bssid);
+			old_addr = nm_utils_hwaddr_ntoa (old_bssid, ARPHRD_ETHER);
 			old_ssid = nm_ap_get_ssid (priv->current_ap);
 		}
 
@@ -3583,7 +3583,7 @@ spec_match_list (NMDevice *device, const GSList *specs)
 	char *hwaddr;
 	gboolean matched;
 
-	hwaddr = nm_ether_ntop ((struct ether_addr *) &priv->perm_hw_addr);
+	hwaddr = nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER);
 	matched = nm_match_spec_hwaddr (specs, hwaddr);
 	g_free (hwaddr);
 
@@ -3828,10 +3828,10 @@ get_property (GObject *object, guint prop_id,
 
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
-		g_value_take_string (value, nm_ether_ntop ((struct ether_addr *) &priv->hw_addr));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->hw_addr, ARPHRD_ETHER));
 		break;
 	case PROP_PERM_HW_ADDRESS:
-		g_value_take_string (value, nm_ether_ntop ((struct ether_addr *) &priv->perm_hw_addr));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER));
 		break;
 	case PROP_MODE:
 		g_value_set_uint (value, nm_device_wifi_get_mode (device));
diff --git a/src/nm-wifi-ap.c b/src/nm-wifi-ap.c
index be836df..6d62307 100644
--- a/src/nm-wifi-ap.c
+++ b/src/nm-wifi-ap.c
@@ -23,6 +23,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <netinet/ether.h>
 
 #include "nm-wifi-ap.h"
 #include "nm-wifi-ap-utils.h"
@@ -183,7 +184,7 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_uint (value, priv->freq);
 		break;
 	case PROP_HW_ADDRESS:
-		g_value_take_string (value, nm_ether_ntop (&priv->address));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->address, ARPHRD_ETHER));
 		break;
 	case PROP_MODE:
 		g_value_set_uint (value, priv->mode);
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index cdad832..836d1c0 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -1576,7 +1576,7 @@ nm_settings_connection_add_seen_bssid (NMSettingsConnection *connection,
 		return;  /* Already in the list */
 
 	/* Add the new BSSID; let the hash take ownership of the allocated BSSID string */
-	bssid_str = nm_ether_ntop (seen_bssid);
+	bssid_str = nm_utils_hwaddr_ntoa (seen_bssid, ARPHRD_ETHER);
 	g_return_if_fail (bssid_str != NULL);
 	g_hash_table_insert (priv->seen_bssids, mac_dup (seen_bssid), bssid_str);
 
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index 910cca3..cb6551d 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -160,7 +160,6 @@ static gboolean
 read_mac_address (shvarFile *ifcfg, const char *key, GByteArray **array, GError **error)
 {
 	char *value = NULL;
-	struct ether_addr *mac;
 
 	g_return_val_if_fail (ifcfg != NULL, FALSE);
 	g_return_val_if_fail (array != NULL, FALSE);
@@ -174,8 +173,8 @@ read_mac_address (shvarFile *ifcfg, const char *key, GByteArray **array, GError
 		return TRUE;
 	}
 
-	mac = ether_aton (value);
-	if (!mac) {
+	*array = nm_utils_hwaddr_atoba (value, ARPHRD_ETHER);
+	if (!*array) {
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 		             "%s: the MAC address '%s' was invalid.", key, value);
 		g_free (value);
@@ -183,8 +182,6 @@ read_mac_address (shvarFile *ifcfg, const char *key, GByteArray **array, GError
 	}
 
 	g_free (value);
-	*array = g_byte_array_sized_new (ETH_ALEN);
-	g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
 	return TRUE;
 }
 
@@ -2901,19 +2898,16 @@ make_wireless_setting (shvarFile *ifcfg,
 
 	value = svGetValue (ifcfg, "BSSID", FALSE);
 	if (value) {
-		struct ether_addr *eth;
 		GByteArray *bssid;
 
-		eth = ether_aton (value);
-		if (!eth) {
+		bssid = nm_utils_hwaddr_atoba (value, ARPHRD_ETHER);
+		if (!bssid) {
 			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 			             "Invalid BSSID '%s'", value);
 			g_free (value);
 			goto error;
 		}
 
-		bssid = g_byte_array_sized_new (ETH_ALEN);
-		g_byte_array_append (bssid, eth->ether_addr_octet, ETH_ALEN);
 		g_object_set (s_wireless, NM_SETTING_WIRELESS_BSSID, bssid, NULL);
 		g_byte_array_free (bssid, TRUE);
 		g_free (value);
diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c
index b4aaa8d..81e466e 100644
--- a/src/settings/plugins/ifnet/connection_parser.c
+++ b/src/settings/plugins/ifnet/connection_parser.c
@@ -509,20 +509,17 @@ static gboolean
 read_mac_address (const char *conn_name, GByteArray **array, GError **error)
 {
 	const char *value = ifnet_get_data (conn_name, "mac");
-	struct ether_addr *mac;
 
 	if (!value || !strlen (value))
 		return TRUE;
 
-	mac = ether_aton (value);
-	if (!mac) {
+	*array = nm_utils_hwaddr_atoba (value, ARPHRD_ETHER);
+	if (!*array) {
 		g_set_error (error, ifnet_plugin_error_quark (), 0,
-			     "The MAC address '%s' was invalid.", value);
+					 "The MAC address '%s' was invalid.", value);
 		return FALSE;
 	}
 
-	*array = g_byte_array_sized_new (ETH_ALEN);
-	g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
 	return TRUE;
 }
 
@@ -1012,18 +1009,15 @@ make_wireless_connection_setting (const char *conn_name,
 	/* BSSID setting */
 	value = wpa_get_value (conn_name, "bssid");
 	if (value) {
-		struct ether_addr *eth;
 		GByteArray *bssid;
 
-		eth = ether_aton (value);
-		if (!eth) {
+		bssid = nm_utils_hwaddr_atoba (value, ARPHRD_ETHER);
+		if (!bssid) {
 			g_set_error (error, ifnet_plugin_error_quark (), 0,
-				     "Invalid BSSID '%s'", value);
+						 "Invalid BSSID '%s'", value);
 			goto error;
 		}
 
-		bssid = g_byte_array_sized_new (ETH_ALEN);
-		g_byte_array_append (bssid, eth->ether_addr_octet, ETH_ALEN);
 		g_object_set (wireless_setting, NM_SETTING_WIRELESS_BSSID,
 			      bssid, NULL);
 		g_byte_array_free (bssid, TRUE);
diff --git a/src/settings/plugins/ifupdown/plugin.c b/src/settings/plugins/ifupdown/plugin.c
index 9679ede..5b83484 100644
--- a/src/settings/plugins/ifupdown/plugin.c
+++ b/src/settings/plugins/ifupdown/plugin.c
@@ -193,7 +193,6 @@ bind_device_to_connection (SCPluginIfupdown *self,
 	NMSetting *s_wired = NULL;
 	NMSetting *s_wifi = NULL;
 	const char *iface, *address;
-	struct ether_addr *tmp_mac;
 
 	iface = g_udev_device_get_name (device);
 	if (!iface) {
@@ -207,16 +206,13 @@ bind_device_to_connection (SCPluginIfupdown *self,
 		return;
 	}
 
-	tmp_mac = ether_aton (address);
+	mac_address = nm_utils_hwaddr_atoba (address, ARPHRD_ETHER);
 	if (!tmp_mac) {
 		PLUGIN_WARN ("SCPluginIfupdown", "failed to parse MAC address '%s' for %s",
 		             address, iface);
 		return;
 	}
 
-	mac_address = g_byte_array_sized_new (ETH_ALEN);
-	g_byte_array_append (mac_address, &(tmp_mac->ether_addr_octet[0]), ETH_ALEN);
-
 	s_wired = nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_WIRED);
 	s_wifi = nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_WIRELESS);
 	if (s_wired) {
diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c
index 4128b9f..dd1868c 100644
--- a/src/settings/plugins/keyfile/reader.c
+++ b/src/settings/plugins/keyfile/reader.c
@@ -34,6 +34,7 @@
 #include <nm-setting-wireless.h>
 #include <nm-setting-bluetooth.h>
 #include <nm-setting-8021x.h>
+#include <nm-utils.h>
 #include <arpa/inet.h>
 #include <netinet/ether.h>
 #include <string.h>
@@ -650,7 +651,6 @@ static void
 mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
 {
 	const char *setting_name = nm_setting_get_name (setting);
-	struct ether_addr *eth;
 	char *tmp_string = NULL, *p;
 	gint *tmp_list;
 	GByteArray *array = NULL;
@@ -668,11 +668,9 @@ mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, cons
 		}
 		if (i == 5) {
 			/* parse as a MAC address */
-			eth = ether_aton (tmp_string);
-			if (eth) {
+			array = nm_utils_hwaddr_atoba (tmp_string, ARPHRD_ETHER);
+			if (array) {
 				g_free (tmp_string);
-				array = g_byte_array_sized_new (ETH_ALEN);
-				g_byte_array_append (array, eth->ether_addr_octet, ETH_ALEN);
 				goto done;
 			}
 		}
diff --git a/src/wimax/nm-device-wimax.c b/src/wimax/nm-device-wimax.c
index 2d8553a..afc0d94 100644
--- a/src/wimax/nm-device-wimax.c
+++ b/src/wimax/nm-device-wimax.c
@@ -1434,7 +1434,7 @@ get_property (GObject *object, guint prop_id,
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		nm_device_wimax_get_hw_address (self, &hw_addr);
-		g_value_take_string (value, nm_ether_ntop (&hw_addr));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (&hw_addr, ARPHRD_ETHER));
 		break;
 	case PROP_ACTIVE_NSP:
 		if (priv->current_nsp)
-- 
1.7.7

>From b3b92309b8cedbfa6dcfdbc6b72a1e6965b9ec97 Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Thu, 13 Oct 2011 16:28:25 -0400
Subject: [PATCH 3/7] libnm-util: add NMSettingInfiniband

---
 libnm-util/Makefile.am             |    2 +
 libnm-util/libnm-util.ver          |    7 +
 libnm-util/nm-connection.c         |   25 ++++-
 libnm-util/nm-connection.h         |    2 +
 libnm-util/nm-setting-infiniband.c |  259 ++++++++++++++++++++++++++++++++++++
 libnm-util/nm-setting-infiniband.h |   82 +++++++++++
 6 files changed, 376 insertions(+), 1 deletions(-)
 create mode 100644 libnm-util/nm-setting-infiniband.c
 create mode 100644 libnm-util/nm-setting-infiniband.h

diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am
index 1327565..aed7f25 100644
--- a/libnm-util/Makefile.am
+++ b/libnm-util/Makefile.am
@@ -16,6 +16,7 @@ libnm_util_include_HEADERS = 		\
 	nm-setting-8021x.h		\
 	nm-setting-bluetooth.h		\
 	nm-setting-connection.h		\
+	nm-setting-infiniband.h		\
 	nm-setting-ip4-config.h		\
 	nm-setting-ip6-config.h		\
 	nm-setting-ppp.h		\
@@ -45,6 +46,7 @@ libnm_util_la_csources = \
 	nm-setting-8021x.c		\
 	nm-setting-bluetooth.c		\
 	nm-setting-connection.c		\
+	nm-setting-infiniband.c		\
 	nm-setting-ip4-config.c		\
 	nm-setting-ip6-config.c		\
 	nm-setting-ppp.c		\
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index 07122de..e41839b 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -20,6 +20,7 @@ global:
 	nm_connection_get_setting_cdma;
 	nm_connection_get_setting_connection;
 	nm_connection_get_setting_gsm;
+	nm_connection_get_setting_infiniband;
 	nm_connection_get_setting_ip4_config;
 	nm_connection_get_setting_ip6_config;
 	nm_connection_get_setting_olpc_mesh;
@@ -216,6 +217,12 @@ global:
 	nm_setting_gsm_get_type;
 	nm_setting_gsm_get_username;
 	nm_setting_gsm_new;
+	nm_setting_infiniband_error_get_type;
+	nm_setting_infiniband_error_quark;
+	nm_setting_infiniband_get_mac_address;
+	nm_setting_infiniband_get_mtu;
+	nm_setting_infiniband_get_type;
+	nm_setting_infiniband_new;
 	nm_setting_ip4_config_add_address;
 	nm_setting_ip4_config_add_dns;
 	nm_setting_ip4_config_add_dns_search;
diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c
index cdc3b81..98a3816 100644
--- a/libnm-util/nm-connection.c
+++ b/libnm-util/nm-connection.c
@@ -34,6 +34,7 @@
 #include "nm-setting-8021x.h"
 #include "nm-setting-bluetooth.h"
 #include "nm-setting-connection.h"
+#include "nm-setting-infiniband.h"
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-ip6-config.h"
 #include "nm-setting-ppp.h"
@@ -135,7 +136,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 static GHashTable *registered_settings = NULL;
 
-#define DEFAULT_MAP_SIZE 16
+#define DEFAULT_MAP_SIZE 17
 
 static struct SettingInfo {
 	const char *name;
@@ -242,6 +243,11 @@ register_default_settings (void)
 	                      NM_SETTING_WIMAX_ERROR,
 	                      1, TRUE);
 
+	register_one_setting (NM_SETTING_INFINIBAND_SETTING_NAME,
+	                      NM_TYPE_SETTING_INFINIBAND,
+	                      NM_SETTING_INFINIBAND_ERROR,
+	                      1, FALSE);
+
 	register_one_setting (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	                      NM_TYPE_SETTING_WIRELESS_SECURITY,
 	                      NM_SETTING_WIRELESS_SECURITY_ERROR,
@@ -1390,6 +1396,23 @@ nm_connection_get_setting_gsm (NMConnection *connection)
 }
 
 /**
+ * nm_connection_get_setting_infiniband:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingInfiniband the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingInfiniband if the connection contains one, otherwise NULL
+ **/
+NMSettingInfiniband *
+nm_connection_get_setting_infiniband (NMConnection *connection)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
+}
+
+/**
  * nm_connection_get_setting_ip4_config:
  * @connection: the #NMConnection
  *
diff --git a/libnm-util/nm-connection.h b/libnm-util/nm-connection.h
index 069dc84..ec6a45e 100644
--- a/libnm-util/nm-connection.h
+++ b/libnm-util/nm-connection.h
@@ -35,6 +35,7 @@
 #include <nm-setting-cdma.h>
 #include <nm-setting-connection.h>
 #include <nm-setting-gsm.h>
+#include <nm-setting-infiniband.h>
 #include <nm-setting-ip4-config.h>
 #include <nm-setting-ip6-config.h>
 #include <nm-setting-olpc-mesh.h>
@@ -186,6 +187,7 @@ NMSettingBluetooth *       nm_connection_get_setting_bluetooth         (NMConnec
 NMSettingCdma *            nm_connection_get_setting_cdma              (NMConnection *connection);
 NMSettingConnection *      nm_connection_get_setting_connection        (NMConnection *connection);
 NMSettingGsm *             nm_connection_get_setting_gsm               (NMConnection *connection);
+NMSettingInfiniband *      nm_connection_get_setting_infiniband        (NMConnection *connection);
 NMSettingIP4Config *       nm_connection_get_setting_ip4_config        (NMConnection *connection);
 NMSettingIP6Config *       nm_connection_get_setting_ip6_config        (NMConnection *connection);
 NMSettingOlpcMesh *        nm_connection_get_setting_olpc_mesh         (NMConnection *connection);
diff --git a/libnm-util/nm-setting-infiniband.c b/libnm-util/nm-setting-infiniband.c
new file mode 100644
index 0000000..9a48812
--- /dev/null
+++ b/libnm-util/nm-setting-infiniband.c
@@ -0,0 +1,259 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * 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 2011 Red Hat, Inc.
+ */
+
+#include <dbus/dbus-glib.h>
+#include <linux/if_infiniband.h>
+
+#include "nm-setting-infiniband.h"
+#include "nm-param-spec-specialized.h"
+#include "nm-utils-private.h"
+
+/**
+ * SECTION:nm-setting-infiniband
+ * @short_description: Describes connection properties for IP-over-Infiniband networks
+ * @include: nm-setting-infiniband.h
+ *
+ * The #NMSettingInfiniband object is a #NMSetting subclass that describes properties
+ * necessary for connection to IP-over-Infiniband networks.
+ **/
+
+/**
+ * nm_setting_infiniband_error_quark:
+ *
+ * Registers an error quark for #NMSettingInfiniband if necessary.
+ *
+ * Returns: the error quark used for #NMSettingInfiniband errors.
+ **/
+GQuark
+nm_setting_infiniband_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-setting-infiniband-error-quark");
+	return quark;
+}
+
+/* This should really be standard. */
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+nm_setting_infiniband_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0) {
+		static const GEnumValue values[] = {
+			/* Unknown error. */
+			ENUM_ENTRY (NM_SETTING_INFINIBAND_ERROR_UNKNOWN, "UnknownError"),
+			/* The specified property was invalid. */
+			ENUM_ENTRY (NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY, "InvalidProperty"),
+			/* The specified property was missing and is required. */
+			ENUM_ENTRY (NM_SETTING_INFINIBAND_ERROR_MISSING_PROPERTY, "MissingProperty"),
+			{ 0, 0, 0 }
+		};
+		etype = g_enum_register_static ("NMSettingInfinibandError", values);
+	}
+	return etype;
+}
+
+G_DEFINE_TYPE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING)
+
+#define NM_SETTING_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandPrivate))
+
+typedef struct {
+	GByteArray *mac_address;
+	guint32 mtu;
+} NMSettingInfinibandPrivate;
+
+enum {
+	PROP_0,
+	PROP_MAC_ADDRESS,
+	PROP_MTU,
+
+	LAST_PROP
+};
+
+/**
+ * nm_setting_infiniband_new:
+ *
+ * Creates a new #NMSettingInfiniband object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingInfiniband object
+ **/
+NMSetting *
+nm_setting_infiniband_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_INFINIBAND, NULL);
+}
+
+/**
+ * nm_setting_infiniband_get_mac_address:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns: the #NMSettingInfiniband:mac-address property of the setting
+ **/
+const GByteArray *
+nm_setting_infiniband_get_mac_address (NMSettingInfiniband *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), NULL);
+
+	return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->mac_address;
+}
+
+/**
+ * nm_setting_infiniband_get_mtu:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns: the #NMSettingInfiniband:mtu property of the setting
+ **/
+guint32
+nm_setting_infiniband_get_mtu (NMSettingInfiniband *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), 0);
+
+	return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->mtu;
+}
+
+
+static gboolean
+verify (NMSetting *setting, GSList *all_settings, GError **error)
+{
+	NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (setting);
+
+	if (priv->mac_address && priv->mac_address->len != INFINIBAND_ALEN) {
+		g_set_error (error,
+		             NM_SETTING_INFINIBAND_ERROR,
+		             NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
+		             NM_SETTING_INFINIBAND_MAC_ADDRESS);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+nm_setting_infiniband_init (NMSettingInfiniband *setting)
+{
+	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_INFINIBAND_SETTING_NAME, NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (object);
+
+	if (priv->mac_address)
+		g_byte_array_free (priv->mac_address, TRUE);
+
+	G_OBJECT_CLASS (nm_setting_infiniband_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_MAC_ADDRESS:
+		if (priv->mac_address)
+			g_byte_array_free (priv->mac_address, TRUE);
+		priv->mac_address = g_value_dup_boxed (value);
+		break;
+	case PROP_MTU:
+		priv->mtu = g_value_get_uint (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMSettingInfiniband *setting = NM_SETTING_INFINIBAND (object);
+
+	switch (prop_id) {
+	case PROP_MAC_ADDRESS:
+		g_value_set_boxed (value, nm_setting_infiniband_get_mac_address (setting));
+		break;
+	case PROP_MTU:
+		g_value_set_uint (value, nm_setting_infiniband_get_mtu (setting));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+	g_type_class_add_private (setting_class, sizeof (NMSettingInfinibandPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+
+	/* Properties */
+	/**
+	 * NMSettingInfiniband:mac-address:
+	 *
+	 * If specified, this connection will only apply to the IPoIB
+	 * device whose permanent MAC address matches. This property does
+	 * not change the MAC address of the device (i.e. MAC spoofing).
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MAC_ADDRESS,
+		 _nm_param_spec_specialized (NM_SETTING_INFINIBAND_MAC_ADDRESS,
+							   "Device MAC Address",
+							   "If specified, this connection will only apply to "
+							   "the IPoIB device whose permanent MAC address matches.  "
+							   "This property does not change the MAC address "
+							   "of the device (i.e. MAC spoofing).",
+							   DBUS_TYPE_G_UCHAR_ARRAY,
+							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	/**
+	 * NMSettingInfiniband:mtu:
+	 *
+	 * If non-zero, only transmit packets of the specified size or smaller,
+	 * breaking larger packets up into multiple frames.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MTU,
+		 g_param_spec_uint (NM_SETTING_INFINIBAND_MTU,
+						"MTU",
+						"If non-zero, only transmit packets of the specified "
+						"size or smaller, breaking larger packets up into "
+						"multiple frames.",
+						0, G_MAXUINT32, 0,
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+}
+
diff --git a/libnm-util/nm-setting-infiniband.h b/libnm-util/nm-setting-infiniband.h
new file mode 100644
index 0000000..be367fc
--- /dev/null
+++ b/libnm-util/nm-setting-infiniband.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * 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 2011 Red Hat, Inc.
+ */
+
+#ifndef NM_SETTING_INFINIBAND_H
+#define NM_SETTING_INFINIBAND_H
+
+#include <nm-setting.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_INFINIBAND            (nm_setting_infiniband_get_type ())
+#define NM_SETTING_INFINIBAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_INFINIBAND, NMSettingInfiniband))
+#define NM_SETTING_INFINIBAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandClass))
+#define NM_IS_SETTING_INFINIBAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_INFINIBAND))
+#define NM_IS_SETTING_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_INFINIBAND))
+#define NM_SETTING_INFINIBAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandClass))
+
+#define NM_SETTING_INFINIBAND_SETTING_NAME "ip-over-infiniband"
+
+/**
+ * NMSettingInfinibandError:
+ * @NM_SETTING_INFINIBAND_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY: the property was invalid
+ * @NM_SETTING_INFINIBAND_ERROR_MISSING_PROPERTY: the property was missing and is
+ * required
+ */
+typedef enum {
+	NM_SETTING_INFINIBAND_ERROR_UNKNOWN = 0,
+	NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
+	NM_SETTING_INFINIBAND_ERROR_MISSING_PROPERTY
+} NMSettingInfinibandError;
+
+#define NM_TYPE_SETTING_INFINIBAND_ERROR (nm_setting_infiniband_error_get_type ()) 
+GType nm_setting_infiniband_error_get_type (void);
+
+#define NM_SETTING_INFINIBAND_ERROR nm_setting_infiniband_error_quark ()
+GQuark nm_setting_infiniband_error_quark (void);
+
+#define NM_SETTING_INFINIBAND_MAC_ADDRESS    "mac-address"
+#define NM_SETTING_INFINIBAND_MTU            "mtu"
+
+typedef struct {
+	NMSetting parent;
+} NMSettingInfiniband;
+
+typedef struct {
+	NMSettingClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+} NMSettingInfinibandClass;
+
+GType nm_setting_infiniband_get_type (void);
+
+NMSetting *       nm_setting_infiniband_new                (void);
+const GByteArray *nm_setting_infiniband_get_mac_address    (NMSettingInfiniband *setting);
+guint32           nm_setting_infiniband_get_mtu            (NMSettingInfiniband *setting);
+
+G_END_DECLS
+
+#endif /* NM_SETTING_INFINIBAND_H */
-- 
1.7.7

>From fbdce8900ca49458a13d5c3f5998ad956d7ccfa5 Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Fri, 21 Oct 2011 09:34:30 -0400
Subject: [PATCH 4/7] ifcfg-rh support for infiniband

---
 src/settings/plugins/ifcfg-rh/common.h |    7 +-
 src/settings/plugins/ifcfg-rh/reader.c |  116 ++++++++++++++++++++++++++++++--
 2 files changed, 113 insertions(+), 10 deletions(-)

diff --git a/src/settings/plugins/ifcfg-rh/common.h b/src/settings/plugins/ifcfg-rh/common.h
index 74a77c4..b45888f 100644
--- a/src/settings/plugins/ifcfg-rh/common.h
+++ b/src/settings/plugins/ifcfg-rh/common.h
@@ -41,9 +41,10 @@
 #define IFCFG_PLUGIN_NAME "ifcfg-rh"
 #define IFCFG_PLUGIN_INFO "(c) 2007 - 2010 Red Hat, Inc.  To report bugs please use the NetworkManager mailing list."
 
-#define TYPE_ETHERNET "Ethernet"
-#define TYPE_WIRELESS "Wireless"
-#define TYPE_BRIDGE   "Bridge"
+#define TYPE_ETHERNET   "Ethernet"
+#define TYPE_WIRELESS   "Wireless"
+#define TYPE_INFINIBAND "Infiniband"
+#define TYPE_BRIDGE     "Bridge"
 
 #define SECRET_FLAG_AGENT "user"
 #define SECRET_FLAG_NOT_SAVED "ask"
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index cb6551d..858ec66 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -157,7 +157,8 @@ make_connection_setting (const char *file,
 }
 
 static gboolean
-read_mac_address (shvarFile *ifcfg, const char *key, GByteArray **array, GError **error)
+read_mac_address (shvarFile *ifcfg, const char *key, int type,
+				  GByteArray **array, GError **error)
 {
 	char *value = NULL;
 
@@ -173,7 +174,7 @@ read_mac_address (shvarFile *ifcfg, const char *key, GByteArray **array, GError
 		return TRUE;
 	}
 
-	*array = nm_utils_hwaddr_atoba (value, ARPHRD_ETHER);
+	*array = nm_utils_hwaddr_atoba (value, type);
 	if (!*array) {
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 		             "%s: the MAC address '%s' was invalid.", key, value);
@@ -263,7 +264,7 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 		goto done;
 	}
 
-	if (!read_mac_address (ifcfg, "HWADDR", &ifcfg_mac, error))
+	if (!read_mac_address (ifcfg, "HWADDR", ARPHRD_ETHER, &ifcfg_mac, error))
 		goto done;
 	/* Ensure we got a MAC */
 	if (!ifcfg_mac) {
@@ -2746,7 +2747,7 @@ make_wireless_setting (shvarFile *ifcfg,
 
 	s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
 
-	if (read_mac_address (ifcfg, "HWADDR", &array, error)) {
+	if (read_mac_address (ifcfg, "HWADDR", ARPHRD_ETHER, &array, error)) {
 		if (array) {
 			g_object_set (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS, array, NULL);
 
@@ -2770,7 +2771,7 @@ make_wireless_setting (shvarFile *ifcfg,
 	}
 
 	array = NULL;
-	if (read_mac_address (ifcfg, "MACADDR", &array, error)) {
+	if (read_mac_address (ifcfg, "MACADDR", ARPHRD_ETHER, &array, error)) {
 		if (array) {
 			g_object_set (s_wireless, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, array, NULL);
 			g_byte_array_free (array, TRUE);
@@ -3076,7 +3077,7 @@ make_wired_setting (shvarFile *ifcfg,
 		g_free (value);
 	}
 
-	if (read_mac_address (ifcfg, "HWADDR", &mac, error)) {
+	if (read_mac_address (ifcfg, "HWADDR", ARPHRD_ETHER, &mac, error)) {
 		if (mac) {
 			g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
 
@@ -3187,7 +3188,7 @@ make_wired_setting (shvarFile *ifcfg,
 	}
 
 	mac = NULL;
-	if (read_mac_address (ifcfg, "MACADDR", &mac, error)) {
+	if (read_mac_address (ifcfg, "MACADDR", ARPHRD_ETHER, &mac, error)) {
 		if (mac) {
 			g_object_set (s_wired, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, mac, NULL);
 			g_byte_array_free (mac, TRUE);
@@ -3292,6 +3293,105 @@ wired_connection_from_ifcfg (const char *file,
 	return connection;
 }
 
+static NMSetting *
+make_infiniband_setting (shvarFile *ifcfg,
+						 const char *file,
+						 gboolean nm_controlled,
+						 char **unmanaged,
+						 GError **error)
+{
+	NMSettingInfiniband *s_infiniband;
+	char *value = NULL;
+	GByteArray *mac = NULL;
+	int mtu;
+
+	s_infiniband = NM_SETTING_INFINIBAND (nm_setting_infiniband_new ());
+
+	value = svGetValue (ifcfg, "MTU", FALSE);
+	if (value) {
+		if (get_int (value, &mtu)) {
+			if (mtu >= 0 && mtu < 65536)
+				g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MTU, mtu, NULL);
+		} else {
+			/* Shouldn't be fatal... */
+			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid MTU '%s'", value);
+		}
+		g_free (value);
+	}
+
+	if (read_mac_address (ifcfg, "HWADDR", ARPHRD_INFINIBAND, &mac, error)) {
+		if (mac) {
+			g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL);
+
+			/* A connection can only be unmanaged if we know the MAC address */
+			if (!nm_controlled) {
+				char *mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_INFINIBAND);
+				*unmanaged = g_strdup_printf ("mac:%s", mac_str);
+				g_free (mac_str);
+			}
+
+			g_byte_array_free (mac, TRUE);
+		}
+	} else {
+		g_object_unref (s_infiniband);
+		return NULL;
+	}
+
+	if (!nm_controlled && !*unmanaged) {
+		/* If NM_CONTROLLED=no but there wasn't a MAC address, notify
+		   the user that the device cannot be unmanaged.
+		 */
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: NM_CONTROLLED was false but HWADDR was missing; device will be managed");
+	}
+
+	return (NMSetting *) s_infiniband;
+}
+
+static NMConnection *
+infiniband_connection_from_ifcfg (const char *file,
+								  shvarFile *ifcfg,
+								  gboolean nm_controlled,
+								  char **unmanaged,
+								  GError **error)
+{
+	NMConnection *connection = NULL;
+	NMSetting *con_setting = NULL;
+	NMSetting *infiniband_setting = NULL;
+
+	g_return_val_if_fail (file != NULL, NULL);
+	g_return_val_if_fail (ifcfg != NULL, NULL);
+
+	connection = nm_connection_new ();
+	if (!connection) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+		             "Failed to allocate new connection for %s.", file);
+		return NULL;
+	}
+
+	con_setting = make_connection_setting (file, ifcfg, NM_SETTING_INFINIBAND_SETTING_NAME, NULL);
+	if (!con_setting) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+		             "Failed to create connection setting.");
+		g_object_unref (connection);
+		return NULL;
+	}
+	nm_connection_add_setting (connection, con_setting);
+
+	infiniband_setting = make_infiniband_setting (ifcfg, file, nm_controlled, unmanaged, error);
+	if (!infiniband_setting) {
+		g_object_unref (connection);
+		return NULL;
+	}
+	nm_connection_add_setting (connection, infiniband_setting);
+
+	if (!nm_connection_verify (connection, error)) {
+		g_object_unref (connection);
+		return NULL;
+	}
+
+	return connection;
+}
+
 static gboolean
 is_wireless_device (const char *iface)
 {
@@ -3472,6 +3572,8 @@ connection_from_file (const char *filename,
 		connection = wired_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
 	else if (!strcasecmp (type, TYPE_WIRELESS))
 		connection = wireless_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
+	else if (!strcasecmp (type, TYPE_INFINIBAND))
+		connection = infiniband_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
 	else if (!strcasecmp (type, TYPE_BRIDGE)) {
 		g_set_error (&error, IFCFG_PLUGIN_ERROR, 0,
 		             "Bridge connections are not yet supported");
-- 
1.7.7

>From 39cfa23d37cbd4872c26b449adee795697194d83 Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Fri, 14 Oct 2011 10:13:49 -0400
Subject: [PATCH 5/7] Split NMDeviceWired out of NMDeviceEthernet, add
 NMDeviceInfiniband

---
 include/NetworkManager.h               |   20 +-
 introspection/nm-device-infiniband.xml |   27 ++
 src/Makefile.am                        |    8 +
 src/logging/nm-logging.c               |    3 +-
 src/logging/nm-logging.h               |    1 +
 src/nm-device-ethernet.c               |  443 +++-----------------------
 src/nm-device-ethernet.h               |   10 +-
 src/nm-device-infiniband.c             |  496 +++++++++++++++++++++++++++++
 src/nm-device-infiniband.h             |   60 ++++
 src/nm-device-wired.c                  |  547 ++++++++++++++++++++++++++++++++
 src/nm-device-wired.h                  |   55 ++++
 src/nm-device.c                        |   28 ++-
 src/nm-udev-manager.c                  |   15 +-
 src/settings/nm-settings.c             |   64 +++--
 14 files changed, 1331 insertions(+), 446 deletions(-)
 create mode 100644 introspection/nm-device-infiniband.xml
 create mode 100644 src/nm-device-infiniband.c
 create mode 100644 src/nm-device-infiniband.h
 create mode 100644 src/nm-device-wired.c
 create mode 100644 src/nm-device-wired.h

diff --git a/include/NetworkManager.h b/include/NetworkManager.h
index 0a00135..96803a0 100644
--- a/include/NetworkManager.h
+++ b/include/NetworkManager.h
@@ -101,20 +101,22 @@ typedef enum {
  * @NM_DEVICE_TYPE_WIMAX: an 802.16e Mobile WiMAX broadband device
  * @NM_DEVICE_TYPE_MODEM: a modem supporting analog telephone, CDMA/EVDO,
  * GSM/UMTS, or LTE network access protocols
+ * @NM_DEVICE_TYPE_INFINIBAND: an IP-over-Infiniband device
  *
  * #NMDeviceType values indicate the type of hardware represented by
  * an #NMDevice.
  **/
 typedef enum {
-	NM_DEVICE_TYPE_UNKNOWN   = 0,
-	NM_DEVICE_TYPE_ETHERNET  = 1,
-	NM_DEVICE_TYPE_WIFI      = 2,
-	NM_DEVICE_TYPE_UNUSED1   = 3,
-	NM_DEVICE_TYPE_UNUSED2   = 4,
-	NM_DEVICE_TYPE_BT        = 5,  /* Bluetooth */
-	NM_DEVICE_TYPE_OLPC_MESH = 6,
-	NM_DEVICE_TYPE_WIMAX     = 7,
-	NM_DEVICE_TYPE_MODEM     = 8,
+	NM_DEVICE_TYPE_UNKNOWN    = 0,
+	NM_DEVICE_TYPE_ETHERNET   = 1,
+	NM_DEVICE_TYPE_WIFI       = 2,
+	NM_DEVICE_TYPE_UNUSED1    = 3,
+	NM_DEVICE_TYPE_UNUSED2    = 4,
+	NM_DEVICE_TYPE_BT         = 5,  /* Bluetooth */
+	NM_DEVICE_TYPE_OLPC_MESH  = 6,
+	NM_DEVICE_TYPE_WIMAX      = 7,
+	NM_DEVICE_TYPE_MODEM      = 8,
+	NM_DEVICE_TYPE_INFINIBAND = 9,
 } NMDeviceType;
 
 /**
diff --git a/introspection/nm-device-infiniband.xml b/introspection/nm-device-infiniband.xml
new file mode 100644
index 0000000..097714c
--- /dev/null
+++ b/introspection/nm-device-infiniband.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0";>
+  <interface name="org.freedesktop.NetworkManager.Device.Infiniband">
+
+    <property name="HwAddress" type="s" access="read">
+      <tp:docstring>
+        Hardware address of the device.
+      </tp:docstring>
+    </property>
+
+    <property name="Carrier" type="b" access="read">
+      <tp:docstring>
+        Indicates whether the physical carrier is found (e.g. whether a cable is plugged in or not).
+      </tp:docstring>
+    </property>
+
+    <signal name="PropertiesChanged">
+        <arg name="properties" type="a{sv}" tp:type="String_Variant_Map">
+            <tp:docstring>
+                A dictionary mapping property names to variant boxed values
+            </tp:docstring>
+        </arg>
+    </signal>
+
+  </interface>
+</node>
diff --git a/src/Makefile.am b/src/Makefile.am
index cbcfdc6..270da00 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -120,12 +120,16 @@ NetworkManager_SOURCES = \
 		nm-device-ethernet.h \
 		nm-device-wifi.c \
 		nm-device-wifi.h \
+		nm-device-wired.c \
+		nm-device-wired.h \
 		nm-device-olpc-mesh.c	\
 		nm-device-olpc-mesh.h	\
 		nm-device-bt.c \
 		nm-device-bt.h \
 		nm-device-modem.h \
 		nm-device-modem.c \
+		nm-device-infiniband.c \
+		nm-device-infiniband.h \
 		nm-wifi-ap.c \
 		nm-wifi-ap.h \
 		nm-wifi-ap-utils.c \
@@ -191,6 +195,9 @@ nm-device-interface-glue.h: $(top_srcdir)/introspection/nm-device.xml
 nm-device-ethernet-glue.h: $(top_srcdir)/introspection/nm-device-ethernet.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-server --output=$@ $<
 
+nm-device-infiniband-glue.h: $(top_srcdir)/introspection/nm-device-infiniband.xml
+	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_infiniband --mode=glib-server --output=$@ $<
+
 nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-server --output=$@ $<
 
@@ -223,6 +230,7 @@ BUILT_SOURCES = \
 	nm-manager-glue.h \
 	nm-device-interface-glue.h \
 	nm-device-ethernet-glue.h \
+	nm-device-infiniband-glue.h \
 	nm-device-wifi-glue.h \
 	nm-device-olpc-mesh-glue.h \
 	nm-device-bt-glue.h \
diff --git a/src/logging/nm-logging.c b/src/logging/nm-logging.c
index 078f152..bc587b2 100644
--- a/src/logging/nm-logging.c
+++ b/src/logging/nm-logging.c
@@ -47,7 +47,7 @@ static guint32 log_domains = \
 	LOGD_DHCP4 | LOGD_DHCP6 | LOGD_PPP | LOGD_IP4 | LOGD_IP6 | LOGD_AUTOIP4 | \
 	LOGD_DNS | LOGD_VPN | LOGD_SHARING | LOGD_SUPPLICANT | LOGD_AGENTS | \
 	LOGD_SETTINGS | LOGD_SUSPEND | LOGD_CORE | LOGD_DEVICE | LOGD_OLPC_MESH | \
-	LOGD_WIMAX;
+	LOGD_WIMAX | LOGD_INFINIBAND;
 
 typedef struct {
 	guint32 num;
@@ -88,6 +88,7 @@ static const LogDesc domain_descs[] = {
 	{ LOGD_DEVICE,    "DEVICE" },
 	{ LOGD_OLPC_MESH, "OLPC" },
 	{ LOGD_WIMAX,     "WIMAX" },
+	{ LOGD_INFINIBAND,"INFINIBAND" },
 	{ 0, NULL }
 };
 
diff --git a/src/logging/nm-logging.h b/src/logging/nm-logging.h
index e3e05f5..586f61c 100644
--- a/src/logging/nm-logging.h
+++ b/src/logging/nm-logging.h
@@ -52,6 +52,7 @@ enum {
 	LOGD_DEVICE     = 0x00200000, /* Device state and activation */
 	LOGD_OLPC_MESH  = 0x00400000,
 	LOGD_WIMAX      = 0x00800000,
+	LOGD_INFINIBAND = 0x01000000,
 };
 
 #define LOGD_DHCP (LOGD_DHCP4 | LOGD_DHCP6)
diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c
index 0d05dd4..33aafec 100644
--- a/src/nm-device-ethernet.c
+++ b/src/nm-device-ethernet.c
@@ -38,8 +38,6 @@
 
 #include <gudev/gudev.h>
 
-#include <netlink/route/addr.h>
-
 #include "nm-glib-compat.h"
 #include "nm-device-ethernet.h"
 #include "nm-device-interface.h"
@@ -49,7 +47,6 @@
 #include "nm-supplicant-manager.h"
 #include "nm-supplicant-interface.h"
 #include "nm-supplicant-config.h"
-#include "nm-netlink-monitor.h"
 #include "nm-system.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-wired.h"
@@ -58,14 +55,12 @@
 #include "ppp-manager/nm-ppp-manager.h"
 #include "nm-logging.h"
 #include "nm-properties-changed-signal.h"
-#include "nm-dhcp-manager.h"
-#include "nm-netlink-utils.h"
 #include "nm-utils.h"
 
 #include "nm-device-ethernet-glue.h"
 
 
-G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE)
+G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE_WIRED)
 
 #define NM_DEVICE_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate))
 
@@ -95,17 +90,8 @@ typedef struct Supplicant {
 } Supplicant;
 
 typedef struct {
-	gboolean            disposed;
-
-	guint8              hw_addr[ETH_ALEN];         /* Currently set MAC address */
 	guint8              perm_hw_addr[ETH_ALEN];    /* Permanent MAC address */
 	guint8              initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */
-	gboolean            carrier;
-
-	NMNetlinkMonitor *  monitor;
-	gulong              link_connected_id;
-	gulong              link_disconnected_id;
-	guint               carrier_action_defer_id;
 
 	Supplicant          supplicant;
 	guint               supplicant_timeout_id;
@@ -176,122 +162,6 @@ nm_ethernet_error_get_type (void)
 }
 
 static void
-carrier_action_defer_clear (NMDeviceEthernet *self)
-{
-	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
-
-	if (priv->carrier_action_defer_id) {
-		g_source_remove (priv->carrier_action_defer_id);
-		priv->carrier_action_defer_id = 0;
-	}
-}
-
-static gboolean
-carrier_action_defer_cb (gpointer user_data)
-{
-	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
-	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
-	NMDeviceState state;
-
-	priv->carrier_action_defer_id = 0;
-
-	state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
-	if (state == NM_DEVICE_STATE_UNAVAILABLE) {
-		if (priv->carrier)
-			nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
-	} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
-		if (!priv->carrier)
-			nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
-	}
-
-	return FALSE;
-}
-
-static void
-set_carrier (NMDeviceEthernet *self,
-             const gboolean carrier,
-             const gboolean defer_action)
-{
-	NMDeviceEthernetPrivate *priv;
-	NMDeviceState state;
-
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
-	if (priv->carrier == carrier)
-		return;
-
-	/* Clear any previous deferred action */
-	carrier_action_defer_clear (self);
-
-	priv->carrier = carrier;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_ETHERNET_CARRIER);
-
-	state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
-	nm_log_info (LOGD_HW | LOGD_ETHER, "(%s): carrier now %s (device state %d%s)",
-	             nm_device_get_iface (NM_DEVICE (self)),
-	             carrier ? "ON" : "OFF",
-	             state,
-	             defer_action ? ", deferring action for 4 seconds" : "");
-
-	if (defer_action)
-		priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self);
-	else
-		carrier_action_defer_cb (self);
-}
-
-static void
-carrier_on (NMNetlinkMonitor *monitor,
-            int idx,
-            gpointer user_data)
-{
-	NMDevice *device = NM_DEVICE (user_data);
-	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
-	guint32 caps;
-
-	/* Make sure signal is for us */
-	if (idx == nm_device_get_ifindex (device)) {
-		/* Ignore spurious netlink messages */
-		caps = nm_device_get_capabilities (device);
-		if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
-			return;
-
-		set_carrier (self, TRUE, FALSE);
-	}
-}
-
-static void
-carrier_off (NMNetlinkMonitor *monitor,
-             int idx,
-             gpointer user_data)
-{
-	NMDevice *device = NM_DEVICE (user_data);
-	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
-	guint32 caps;
-
-	/* Make sure signal is for us */
-	if (idx == nm_device_get_ifindex (device)) {
-		NMDeviceState state;
-		gboolean defer = FALSE;
-
-		/* Ignore spurious netlink messages */
-		caps = nm_device_get_capabilities (device);
-		if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
-			return;
-
-		/* Defer carrier-off event actions while connected by a few seconds
-		 * so that tripping over a cable, power-cycling a switch, or breaking
-		 * off the RJ45 locking tab isn't so catastrophic.
-		 */
-		state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
-		if (state > NM_DEVICE_STATE_DISCONNECTED)
-			defer = TRUE;
-
-		set_carrier (self, FALSE, defer);
-	}
-}
-
-static void
 _update_s390_subchannels (NMDeviceEthernet *self)
 {
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
@@ -402,7 +272,6 @@ constructor (GType type,
 	GObject *object;
 	NMDeviceEthernetPrivate *priv;
 	NMDevice *self;
-	guint32 caps;
 
 	object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type,
 	                                                                        n_construct_params,
@@ -420,59 +289,6 @@ constructor (GType type,
 	/* s390 stuff */
 	_update_s390_subchannels (NM_DEVICE_ETHERNET (self));
 
-	caps = nm_device_get_capabilities (self);
-	if (caps & NM_DEVICE_CAP_CARRIER_DETECT) {
-		GError *error = NULL;
-		guint32 ifflags = 0;
-
-		/* Only listen to netlink for cards that support carrier detect */
-		priv->monitor = nm_netlink_monitor_get ();
-
-		priv->link_connected_id = g_signal_connect (priv->monitor, "carrier-on",
-		                                            G_CALLBACK (carrier_on),
-		                                            self);
-		priv->link_disconnected_id = g_signal_connect (priv->monitor, "carrier-off",
-		                                               G_CALLBACK (carrier_off),
-		                                               self);
-
-		/* Get initial link state */
-		if (!nm_netlink_monitor_get_flags_sync (priv->monitor,
-		                                        nm_device_get_ifindex (NM_DEVICE (self)),
-		                                        &ifflags,
-		                                        &error)) {
-			nm_log_warn (LOGD_HW | LOGD_ETHER,
-			             "(%s): couldn't get initial carrier state: (%d) %s",
-			             nm_device_get_iface (NM_DEVICE (self)),
-			             error ? error->code : -1,
-			             (error && error->message) ? error->message : "unknown");
-			g_clear_error (&error);
-		} else
-			priv->carrier = !!(ifflags & IFF_LOWER_UP);
-
-		nm_log_info (LOGD_HW | LOGD_ETHER,
-		             "(%s): carrier is %s",
-		             nm_device_get_iface (NM_DEVICE (self)),
-		             priv->carrier ? "ON" : "OFF");
-
-		/* Request link state again just in case an error occurred getting the
-		 * initial link state.
-		 */
-		if (!nm_netlink_monitor_request_status (priv->monitor, &error)) {
-			nm_log_warn (LOGD_HW | LOGD_ETHER,
-			             "(%s): couldn't request carrier state: (%d) %s",
-			             nm_device_get_iface (NM_DEVICE (self)),
-			             error ? error->code : -1,
-			             (error && error->message) ? error->message : "unknown");
-			g_clear_error (&error);
-		}
-	} else {
-		nm_log_info (LOGD_HW | LOGD_ETHER,
-		             "(%s): driver '%s' does not support carrier detection.",
-		             nm_device_get_iface (self),
-		             nm_device_get_driver (self));
-		priv->carrier = TRUE;
-	}
-
 	return object;
 }
 
@@ -545,24 +361,6 @@ real_take_down (NMDevice *dev)
 	}
 }
 
-static gboolean
-real_hw_is_up (NMDevice *device)
-{
-	return nm_system_iface_is_up (nm_device_get_ip_ifindex (device));
-}
-
-static gboolean
-real_hw_bring_up (NMDevice *dev, gboolean *no_firmware)
-{
-	return nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware);
-}
-
-static void
-real_hw_take_down (NMDevice *dev)
-{
-	nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL);
-}
-
 NMDevice *
 nm_device_ethernet_new (const char *udi,
 						const char *iface,
@@ -582,24 +380,6 @@ nm_device_ethernet_new (const char *udi,
 }
 
 
-/*
- * nm_device_ethernet_get_address
- *
- * Get a device's hardware address
- *
- */
-void
-nm_device_ethernet_get_address (NMDeviceEthernet *self, struct ether_addr *addr)
-{
-	NMDeviceEthernetPrivate *priv;
-
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (addr != NULL);
-
-	priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
-	memcpy (addr, &priv->hw_addr, sizeof (priv->hw_addr));
-}
-
 /* Returns speed in Mb/s */
 static guint32
 nm_device_ethernet_get_speed (NMDeviceEthernet *self)
@@ -643,12 +423,14 @@ out:
 static void
 _update_hw_addr (NMDeviceEthernet *self, const guint8 *addr)
 {
-	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+	guint8 *current_addr;
 
 	g_return_if_fail (addr != NULL);
 
-	if (memcmp (&priv->hw_addr, addr, ETH_ALEN)) {
-		memcpy (&priv->hw_addr, addr, ETH_ALEN);
+	current_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (self));
+
+	if (memcmp (current_addr, addr, ETH_ALEN)) {
+		memcpy (current_addr, addr, ETH_ALEN);
 		g_object_notify (G_OBJECT (self), NM_DEVICE_ETHERNET_HW_ADDRESS);
 	}
 }
@@ -657,7 +439,7 @@ static gboolean
 _set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail)
 {
 	NMDevice *dev = NM_DEVICE (self);
-	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+	guint8 *current_addr;
 	const char *iface;
 	char *mac_str = NULL;
 	gboolean success = FALSE;
@@ -666,18 +448,18 @@ _set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail)
 
 	iface = nm_device_get_iface (dev);
 
-	mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
-	                           addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
-
 	/* Do nothing if current MAC is same */
-	if (!memcmp (&priv->hw_addr, addr, ETH_ALEN)) {
+	current_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (self));
+	if (!memcmp (current_addr, addr, ETH_ALEN)) {
 		nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): no MAC address change needed", iface);
-		g_free (mac_str);
 		return TRUE;
 	}
 
+	mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+	                           addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
 	/* Can't change MAC address while device is up */
-	real_hw_take_down (dev);
+	nm_device_hw_take_down (dev, FALSE);
 
 	success = nm_system_iface_set_mac (nm_device_get_ip_ifindex (dev), (struct ether_addr *) addr);
 	if (success) {
@@ -689,7 +471,7 @@ _set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail)
 		nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "(%s): failed to %s MAC address to %s",
 		             iface, detail, mac_str);
 	}
-	real_hw_bring_up (dev, NULL);
+	nm_device_hw_bring_up (dev, FALSE, NULL);
 	g_free (mac_str);
 
 	return success;
@@ -698,28 +480,16 @@ _set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail)
 static void
 real_update_hw_address (NMDevice *dev)
 {
-	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
-	struct ifreq req;
-	int fd;
+	guint8 *hw_addr, old_addr[ETH_ALEN];
 
-	fd = socket (PF_INET, SOCK_DGRAM, 0);
-	if (fd < 0) {
-		nm_log_warn (LOGD_HW, "couldn't open control socket.");
-		return;
-	}
+	hw_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (dev));
+	memcpy (old_addr, hw_addr, ETH_ALEN);
 
-	memset (&req, 0, sizeof (struct ifreq));
-	strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ);
+	NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->update_hw_address (dev);
 
-	errno = 0;
-	if (ioctl (fd, SIOCGIFHWADDR, &req) < 0) {
-		nm_log_err (LOGD_HW | LOGD_ETHER,
-		            "(%s) failed to read hardware address (error %d)",
-		            nm_device_get_iface (dev), errno);
-	} else
-		_update_hw_addr (self, (const guint8 *) &req.ifr_hwaddr.sa_data);
-
-	close (fd);
+	hw_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (dev));
+	if (memcmp (old_addr, hw_addr, ETH_ALEN))
+		g_object_notify (G_OBJECT (dev), NM_DEVICE_ETHERNET_HW_ADDRESS);
 }
 
 static void
@@ -749,10 +519,13 @@ real_update_permanent_hw_address (NMDevice *dev)
 	errno = 0;
 	ret = ioctl (fd, SIOCETHTOOL, &req);
 	if ((ret < 0) || !nm_ethernet_address_is_valid ((struct ether_addr *) epaddr->data)) {
+		guint8 *current_addr;
+
 		nm_log_err (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)",
 		            nm_device_get_iface (dev), errno);
 		/* Fall back to current address */
-		memcpy (epaddr->data, &priv->hw_addr, ETH_ALEN);
+		current_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (self));
+		memcpy (epaddr->data, current_addr, ETH_ALEN);
 	}
 
 	if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) {
@@ -768,6 +541,7 @@ real_update_initial_hw_address (NMDevice *dev)
 {
 	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+	guint8 *current_addr;
 	char *mac_str = NULL;
 	guint8 *addr = priv->initial_hw_addr;
 	guint8 zero[ETH_ALEN] = {0,0,0,0,0,0};
@@ -775,11 +549,12 @@ real_update_initial_hw_address (NMDevice *dev)
 	/* This sets initial MAC address from current MAC address. It should only
 	 * be called from NMDevice constructor() to really get the initial address.
 	 */
-	if (!memcmp (&priv->hw_addr, &zero, ETH_ALEN))
+	current_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (self));
+	if (!memcmp (current_addr, &zero, ETH_ALEN))
 		real_update_hw_address (dev);
 
-	if (memcmp (&priv->initial_hw_addr, &priv->hw_addr, ETH_ALEN))
-		memcpy (&priv->initial_hw_addr, &priv->hw_addr, ETH_ALEN);
+	if (memcmp (&priv->initial_hw_addr, current_addr, ETH_ALEN))
+		memcpy (&priv->initial_hw_addr, current_addr, ETH_ALEN);
 
 	mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
 	                           addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
@@ -809,34 +584,6 @@ real_get_generic_capabilities (NMDevice *dev)
 }
 
 static gboolean
-real_can_interrupt_activation (NMDevice *dev)
-{
-	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
-	gboolean interrupt = FALSE;
-
-	/* Devices that support carrier detect can interrupt activation
-	 * if the link becomes inactive.
-	 */
-	if (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_CARRIER_DETECT) {
-		if (NM_DEVICE_ETHERNET_GET_PRIVATE (self)->carrier == FALSE)
-			interrupt = TRUE;
-	}
-	return interrupt;
-}
-
-static gboolean
-real_is_available (NMDevice *dev)
-{
-	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
-
-	/* Can't do anything if there isn't a carrier */
-	if (!NM_DEVICE_ETHERNET_GET_PRIVATE (self)->carrier)
-		return FALSE;
-
-	return TRUE;
-}
-
-static gboolean
 match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac)
 {
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
@@ -1798,87 +1545,19 @@ wired_match_config (NMDevice *self, NMConnection *connection)
 	return TRUE;
 }
 
-static gboolean
-ip4_match_config (NMDevice *self, NMConnection *connection)
-{
-	NMSettingIP4Config *s_ip4;
-	int i, num;
-	GSList *leases, *iter;
-	NMDHCPManager *dhcp_mgr;
-	const char *method;
-
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	if (!s_ip4)
-		return FALSE;
-
-	/* Get any saved leases that apply to this connection */
-	dhcp_mgr = nm_dhcp_manager_get ();
-	leases = nm_dhcp_manager_get_lease_config (dhcp_mgr,
-	                                           nm_device_get_iface (self),
-	                                           nm_connection_get_uuid (connection));
-	g_object_unref (dhcp_mgr);
-
-	method = nm_setting_ip4_config_get_method (s_ip4);
-	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
-		gboolean found = FALSE;
-
-		/* Find at least one lease's address on the device */
-		for (iter = leases; iter; iter = g_slist_next (iter)) {
-			NMIP4Config *ip4_config = iter->data;
-			NMIP4Address *addr = nm_ip4_config_get_address (ip4_config, 0);
-			struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) };
-
-			if (addr && nm_netlink_find_address (nm_device_get_ip_ifindex (self),
-			                                     AF_INET,
-			                                     &tmp,
-			                                     nm_ip4_address_get_prefix (addr))) {
-				found = TRUE; /* Yay, device has same address as a lease */
-				break;
-			}
-		}
-		g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
-		g_slist_free (leases);
-		return found;
-	} else {
-		/* Maybe the connection used to be DHCP and there are stale leases; ignore them */
-		g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
-		g_slist_free (leases);
-	}
-
-	/* 'shared' and 'link-local' aren't supported methods because 'shared'
-	 * requires too much iptables and dnsmasq state to be reclaimed, and
-	 * avahi-autoipd isn't smart enough to allow the link-local address to be
-	 * determined at any point other than when it was first assigned.
-	 */
-	if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
-		return FALSE;
-
-	/* Everything below for static addressing */
-
-	/* Find all IP4 addresses of this connection on the device */
-	num = nm_setting_ip4_config_get_num_addresses (s_ip4);
-	for (i = 0; i < num; i++) {
-		NMIP4Address *addr = nm_setting_ip4_config_get_address (s_ip4, i);
-		struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) };
-
-		if (!nm_netlink_find_address (nm_device_get_ip_ifindex (self),
-		                              AF_INET,
-		                              &tmp,
-		                              nm_ip4_address_get_prefix (addr)))
-			return FALSE;
-	}
-
-	/* Success; all the connection's static IP addresses are assigned to the device */
-	return TRUE;
-}
-
 static NMConnection *
 connection_match_config (NMDevice *self, const GSList *connections)
 {
-	GSList *iter;
+	const GSList *iter;
+	GSList *wired_matches;
 	NMSettingConnection *s_con;
+	NMConnection *match;
 
-	for (iter = (GSList *) connections; iter; iter = g_slist_next (iter)) {
+	/* First narrow @connections down to those that match in their
+	 * NMSettingWired configuration.
+	 */
+	wired_matches = NULL;
+	for (iter = connections; iter; iter = iter->next) {
 		NMConnection *candidate = NM_CONNECTION (iter->data);
 
 		s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
@@ -1896,13 +1575,15 @@ connection_match_config (NMDevice *self, const GSList *connections)
 		if (!wired_match_config (self, candidate))
 			continue;
 
-		if (!ip4_match_config (self, candidate))
-			continue;
-
-		return candidate;
+		wired_matches = g_slist_prepend (wired_matches, candidate);
 	}
 
-	return NULL;
+	/* Now pass those to the super method, which will check IP config */
+	wired_matches = g_slist_reverse (wired_matches);
+	match = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->connection_match_config (self, wired_matches);
+	g_slist_free (wired_matches);
+
+	return match;
 }
 
 static void
@@ -1911,29 +1592,6 @@ dispose (GObject *object)
 	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object);
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
-	if (priv->link_connected_id) {
-		g_signal_handler_disconnect (priv->monitor, priv->link_connected_id);
-		priv->link_connected_id = 0;
-	}
-	if (priv->link_disconnected_id) {
-		g_signal_handler_disconnect (priv->monitor, priv->link_disconnected_id);
-		priv->link_disconnected_id = 0;
-	}
-
-	carrier_action_defer_clear (self);
-
-	if (priv->monitor) {
-		g_object_unref (priv->monitor);
-		priv->monitor = NULL;
-	}
-
 	g_free (priv->subchan1);
 	g_free (priv->subchan2);
 	g_free (priv->subchan3);
@@ -1948,10 +1606,12 @@ get_property (GObject *object, guint prop_id,
 {
 	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object);
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+	guint8 *current_addr;
 
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
-		g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->hw_addr, ARPHRD_ETHER));
+		current_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (self));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (current_addr, ARPHRD_ETHER));
 		break;
 	case PROP_PERM_HW_ADDRESS:
 		g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER));
@@ -1960,7 +1620,7 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_uint (value, nm_device_ethernet_get_speed (self));
 		break;
 	case PROP_CARRIER:
-		g_value_set_boolean (value, priv->carrier);
+		g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (self)));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1994,18 +1654,13 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
 	object_class->set_property = set_property;
 
 	parent_class->get_generic_capabilities = real_get_generic_capabilities;
-	parent_class->hw_is_up = real_hw_is_up;
-	parent_class->hw_bring_up = real_hw_bring_up;
-	parent_class->hw_take_down = real_hw_take_down;
 	parent_class->is_up = real_is_up;
 	parent_class->bring_up = real_bring_up;
 	parent_class->take_down = real_take_down;
-	parent_class->can_interrupt_activation = real_can_interrupt_activation;
 	parent_class->update_hw_address = real_update_hw_address;
 	parent_class->update_permanent_hw_address = real_update_permanent_hw_address;
 	parent_class->update_initial_hw_address = real_update_initial_hw_address;
 	parent_class->get_best_auto_connection = real_get_best_auto_connection;
-	parent_class->is_available = real_is_available;
 	parent_class->check_connection_compatible = real_check_connection_compatible;
 	parent_class->complete_connection = real_complete_connection;
 
diff --git a/src/nm-device-ethernet.h b/src/nm-device-ethernet.h
index b9e2afd..7b61f8b 100644
--- a/src/nm-device-ethernet.h
+++ b/src/nm-device-ethernet.h
@@ -23,9 +23,8 @@
 #define NM_DEVICE_ETHERNET_H
 
 #include <glib-object.h>
-#include <net/ethernet.h>
 
-#include "nm-device.h"
+#include "nm-device-wired.h"
 
 G_BEGIN_DECLS
 
@@ -42,11 +41,11 @@ G_BEGIN_DECLS
 #define NM_DEVICE_ETHERNET_CARRIER "carrier"
 
 typedef struct {
-	NMDevice parent;
+	NMDeviceWired parent;
 } NMDeviceEthernet;
 
 typedef struct {
-	NMDeviceClass parent;
+	NMDeviceWiredClass parent;
 
 	/* Signals */
 	void (*properties_changed) (NMDeviceEthernet *device, GHashTable *properties);
@@ -60,9 +59,6 @@ NMDevice *nm_device_ethernet_new (const char *udi,
                                   const char *iface,
                                   const char *driver);
 
-void nm_device_ethernet_get_address (NMDeviceEthernet *dev,
-                                     struct ether_addr *addr);
-
 G_END_DECLS
 
 #endif	/* NM_DEVICE_ETHERNET_H */
diff --git a/src/nm-device-infiniband.c b/src/nm-device-infiniband.c
new file mode 100644
index 0000000..3f8ead3
--- /dev/null
+++ b/src/nm-device-infiniband.c
@@ -0,0 +1,496 @@
+/* -*- 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 2011 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <linux/if_infiniband.h>
+#include <netinet/ether.h>
+
+#include "nm-device-infiniband.h"
+#include "nm-device-interface.h"
+#include "nm-logging.h"
+#include "nm-properties-changed-signal.h"
+#include "nm-utils.h"
+#include "NetworkManagerUtils.h"
+#if 0
+#include "nm-device-private.h"
+#include "nm-activation-request.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-wired.h"
+#include "nm-dhcp-manager.h"
+#include "nm-netlink-utils.h"
+#endif
+
+#include "nm-device-infiniband-glue.h"
+
+
+G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE_WIRED)
+
+#define NM_DEVICE_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandPrivate))
+
+typedef enum
+{
+	NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND = 0,
+	NM_INFINIBAND_ERROR_CONNECTION_INVALID,
+	NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE,
+} NMInfinibandError;
+
+#define NM_INFINIBAND_ERROR (nm_infiniband_error_quark ())
+#define NM_TYPE_INFINIBAND_ERROR (nm_infiniband_error_get_type ()) 
+
+typedef struct {
+	int dummy;
+} NMDeviceInfinibandPrivate;
+
+enum {
+	PROPERTIES_CHANGED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_CARRIER,
+
+	LAST_PROP
+};
+
+static GQuark
+nm_infiniband_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("nm-infiniband-error");
+	return quark;
+}
+
+/* This should really be standard. */
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+static GType
+nm_infiniband_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0) {
+		static const GEnumValue values[] = {
+			/* Connection was not a wired connection. */
+			ENUM_ENTRY (NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND, "ConnectionNotInfiniband"),
+			/* Connection was not a valid wired connection. */
+			ENUM_ENTRY (NM_INFINIBAND_ERROR_CONNECTION_INVALID, "ConnectionInvalid"),
+			/* Connection does not apply to this device. */
+			ENUM_ENTRY (NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE, "ConnectionIncompatible"),
+			{ 0, 0, 0 }
+		};
+		etype = g_enum_register_static ("NMInfinibandError", values);
+	}
+	return etype;
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMDeviceInfinibandPrivate *priv;
+	NMDevice *self;
+
+	object = G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructor (type,
+	                                                                        n_construct_params,
+	                                                                        construct_params);
+	if (!object)
+		return NULL;
+
+	self = NM_DEVICE (object);
+	priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (self);
+
+	nm_log_dbg (LOGD_HW | LOGD_INFINIBAND, "(%s): kernel ifindex %d",
+	            nm_device_get_iface (NM_DEVICE (self)),
+	            nm_device_get_ifindex (NM_DEVICE (self)));
+
+	return object;
+}
+
+static void
+nm_device_infiniband_init (NMDeviceInfiniband * self)
+{
+}
+
+NMDevice *
+nm_device_infiniband_new (const char *udi,
+						  const char *iface,
+						  const char *driver)
+{
+	g_return_val_if_fail (udi != NULL, NULL);
+	g_return_val_if_fail (iface != NULL, NULL);
+	g_return_val_if_fail (driver != NULL, NULL);
+
+	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND,
+	                                  NM_DEVICE_INTERFACE_UDI, udi,
+	                                  NM_DEVICE_INTERFACE_IFACE, iface,
+	                                  NM_DEVICE_INTERFACE_DRIVER, driver,
+	                                  NM_DEVICE_INTERFACE_TYPE_DESC, "Infiniband",
+	                                  NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND,
+	                                  NULL);
+}
+
+
+static void
+real_update_hw_address (NMDevice *dev)
+{
+	guint8 *hw_addr, old_addr[INFINIBAND_ALEN];
+
+	hw_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (dev));
+	memcpy (old_addr, hw_addr, INFINIBAND_ALEN);
+
+	NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->update_hw_address (dev);
+
+	hw_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (dev));
+	if (memcmp (old_addr, hw_addr, INFINIBAND_ALEN))
+		g_object_notify (G_OBJECT (dev), NM_DEVICE_INFINIBAND_HW_ADDRESS);
+}
+
+static guint32
+real_get_generic_capabilities (NMDevice *dev)
+{
+	return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NM_SUPPORTED;
+}
+
+static NMConnection *
+real_get_best_auto_connection (NMDevice *dev,
+                               GSList *connections,
+                               char **specific_object)
+{
+	GSList *iter;
+
+	for (iter = connections; iter; iter = g_slist_next (iter)) {
+		NMConnection *connection = NM_CONNECTION (iter->data);
+		NMSettingConnection *s_con;
+		NMSettingInfiniband *s_infiniband;
+		const char *connection_type;
+
+		s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+		g_assert (s_con);
+
+		connection_type = nm_setting_connection_get_connection_type (s_con);
+
+		if (strcmp (connection_type, NM_SETTING_INFINIBAND_SETTING_NAME))
+			continue;
+		if (!nm_setting_connection_get_autoconnect (s_con))
+			continue;
+
+		s_infiniband = (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
+		if (!s_infiniband)
+			continue;
+
+		if (s_infiniband) {
+			guint8 *hwaddr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (dev));
+			const GByteArray *mac;
+
+			mac = nm_setting_infiniband_get_mac_address (s_infiniband);
+			if (mac && memcmp (mac->data, hwaddr, INFINIBAND_ALEN))
+				continue;
+		}
+
+		return connection;
+	}
+	return NULL;
+}
+
+static NMActStageReturn
+real_act_stage4_get_ip4_config (NMDevice *device,
+                                NMIP4Config **config,
+                                NMDeviceStateReason *reason)
+{
+	NMActStageReturn ret;
+
+	g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+	g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
+	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+	/* Chain up to parent */
+	ret = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage4_get_ip4_config (device, config, reason);
+
+	if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
+		NMConnection *connection;
+		NMSettingInfiniband *s_infiniband;
+		guint32 mtu;
+
+		connection = nm_act_request_get_connection (nm_device_get_act_request (device));
+		g_assert (connection);
+		s_infiniband = NM_SETTING_INFINIBAND (nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND));
+		g_assert (s_infiniband);
+
+		/* MTU override */
+		mtu = nm_setting_infiniband_get_mtu (s_infiniband);
+		if (mtu)
+			nm_ip4_config_set_mtu (*config, mtu);
+	}
+
+	return ret;
+}
+
+static gboolean
+real_check_connection_compatible (NMDevice *device,
+                                  NMConnection *connection,
+                                  GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingInfiniband *s_infiniband;
+	const char *connection_type;
+	const GByteArray *mac;
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+
+	connection_type = nm_setting_connection_get_connection_type (s_con);
+	if (strcmp (connection_type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
+		g_set_error (error,
+		             NM_INFINIBAND_ERROR,
+					 NM_INFINIBAND_ERROR_CONNECTION_NOT_INFINIBAND,
+		             "The connection was not an Infiniband connection.");
+		return FALSE;
+	}
+
+	s_infiniband = (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
+	if (!s_infiniband) {
+		g_set_error (error,
+		             NM_INFINIBAND_ERROR, NM_INFINIBAND_ERROR_CONNECTION_INVALID,
+		             "The connection was not a valid infiniband connection.");
+		return FALSE;
+	}
+
+	if (s_infiniband) {
+		guint8 *hwaddr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (device));
+
+		mac = nm_setting_infiniband_get_mac_address (s_infiniband);
+		if (mac && memcmp (mac->data, hwaddr, INFINIBAND_ALEN)) {
+			g_set_error (error,
+			             NM_INFINIBAND_ERROR,
+						 NM_INFINIBAND_ERROR_CONNECTION_INCOMPATIBLE,
+			             "The connection's MAC address did not match this device.");
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+static gboolean
+real_complete_connection (NMDevice *device,
+                          NMConnection *connection,
+                          const char *specific_object,
+                          const GSList *existing_connections,
+                          GError **error)
+{
+	NMSettingInfiniband *s_infiniband;
+	const GByteArray *setting_mac;
+	guint8 *hwaddr;
+
+	nm_utils_complete_generic (connection,
+	                           NM_SETTING_INFINIBAND_SETTING_NAME,
+	                           existing_connections,
+	                           _("Infiniband connection %d"),
+	                           NULL,
+	                           TRUE);
+
+	s_infiniband = (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
+	if (!s_infiniband) {
+		s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new ();
+		nm_connection_add_setting (connection, NM_SETTING (s_infiniband));
+	}
+
+	hwaddr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (device));
+	setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband);
+	if (setting_mac) {
+		/* Make sure the setting MAC (if any) matches the device's MAC */
+		if (memcmp (setting_mac->data, hwaddr, INFINIBAND_ALEN)) {
+			g_set_error_literal (error,
+			                     NM_SETTING_INFINIBAND_ERROR,
+			                     NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
+			                     NM_SETTING_INFINIBAND_MAC_ADDRESS);
+			return FALSE;
+		}
+	} else {
+		GByteArray *mac;
+
+		/* Lock the connection to this device by default */
+		mac = g_byte_array_sized_new (INFINIBAND_ALEN);
+		g_byte_array_append (mac, hwaddr, INFINIBAND_ALEN);
+		g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL);
+		g_byte_array_free (mac, TRUE);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+spec_match_list (NMDevice *device, const GSList *specs)
+{
+	char *hwaddr;
+	gboolean matched;
+
+	hwaddr = nm_utils_hwaddr_ntoa (nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (device)), ARPHRD_INFINIBAND);
+	matched = nm_match_spec_hwaddr (specs, hwaddr);
+	g_free (hwaddr);
+
+	return matched;
+}
+
+static gboolean
+infiniband_match_config (NMDevice *self, NMConnection *connection)
+{
+	NMSettingInfiniband *s_infiniband;
+	const GByteArray *s_mac;
+
+	s_infiniband = (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
+	if (!s_infiniband)
+		return FALSE;
+
+	/* MAC address check */
+	s_mac = nm_setting_infiniband_get_mac_address (s_infiniband);
+	if (s_mac && memcmp (s_mac->data, nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (self)), INFINIBAND_ALEN))
+		return FALSE;
+
+	return TRUE;
+}
+
+static NMConnection *
+connection_match_config (NMDevice *self, const GSList *connections)
+{
+	const GSList *iter;
+	GSList *infiniband_matches;
+	NMSettingConnection *s_con;
+	NMConnection *match;
+
+	/* First narrow @connections down to those that match in their
+	 * NMSettingInfiniband configuration.
+	 */
+	infiniband_matches = NULL;
+	for (iter = connections; iter; iter = iter->next) {
+		NMConnection *candidate = NM_CONNECTION (iter->data);
+
+		s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
+		g_assert (s_con);
+		if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_INFINIBAND_SETTING_NAME))
+			continue;
+
+		if (!infiniband_match_config (self, candidate))
+			continue;
+
+		infiniband_matches = g_slist_prepend (infiniband_matches, candidate);
+	}
+
+	/* Now pass those to the super method, which will check IP config */
+	infiniband_matches = g_slist_reverse (infiniband_matches);
+	match = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->connection_match_config (self, infiniband_matches);
+	g_slist_free (infiniband_matches);
+
+	return match;
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	guint8 *current_addr;
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		current_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (object));
+		g_value_take_string (value, nm_utils_hwaddr_ntoa (current_addr, ARPHRD_INFINIBAND));
+		break;
+	case PROP_CARRIER:
+		g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (object)));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec)
+{
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (NMDeviceInfinibandPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->set_property = set_property;
+
+	parent_class->get_generic_capabilities = real_get_generic_capabilities;
+	parent_class->update_hw_address = real_update_hw_address;
+	parent_class->get_best_auto_connection = real_get_best_auto_connection;
+	parent_class->check_connection_compatible = real_check_connection_compatible;
+	parent_class->complete_connection = real_complete_connection;
+
+	parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
+	parent_class->spec_match_list = spec_match_list;
+	parent_class->connection_match_config = connection_match_config;
+
+	/* properties */
+	g_object_class_install_property
+		(object_class, PROP_HW_ADDRESS,
+		 g_param_spec_string (NM_DEVICE_INFINIBAND_HW_ADDRESS,
+							  "Active MAC Address",
+							  "Currently set hardware MAC address",
+							  NULL,
+							  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_INFINIBAND_CARRIER,
+							   "Carrier",
+							   "Carrier",
+							   FALSE,
+							   G_PARAM_READABLE));
+
+	/* Signals */
+	signals[PROPERTIES_CHANGED] = 
+		nm_properties_changed_signal_new (object_class,
+										  G_STRUCT_OFFSET (NMDeviceInfinibandClass, properties_changed));
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+									 &dbus_glib_nm_device_infiniband_object_info);
+
+	dbus_g_error_domain_register (NM_INFINIBAND_ERROR, NULL, NM_TYPE_INFINIBAND_ERROR);
+}
diff --git a/src/nm-device-infiniband.h b/src/nm-device-infiniband.h
new file mode 100644
index 0000000..d70abd9
--- /dev/null
+++ b/src/nm-device-infiniband.h
@@ -0,0 +1,60 @@
+/* -*- 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 2011 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_INFINIBAND_H
+#define NM_DEVICE_INFINIBAND_H
+
+#include <glib-object.h>
+
+#include "nm-device-wired.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_INFINIBAND			(nm_device_infiniband_get_type ())
+#define NM_DEVICE_INFINIBAND(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfiniband))
+#define NM_DEVICE_INFINIBAND_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass))
+#define NM_IS_DEVICE_INFINIBAND(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_INFINIBAND))
+#define NM_IS_DEVICE_INFINIBAND_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_DEVICE_INFINIBAND))
+#define NM_DEVICE_INFINIBAND_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass))
+
+#define NM_DEVICE_INFINIBAND_HW_ADDRESS "hw-address"
+#define NM_DEVICE_INFINIBAND_CARRIER "carrier"
+
+typedef struct {
+	NMDeviceWired parent;
+} NMDeviceInfiniband;
+
+typedef struct {
+	NMDeviceWiredClass parent;
+
+	/* Signals */
+	void (*properties_changed) (NMDeviceInfiniband *device, GHashTable *properties);
+} NMDeviceInfinibandClass;
+
+
+GType nm_device_infiniband_get_type (void);
+
+NMDevice *nm_device_infiniband_new (const char *udi,
+									const char *iface,
+									const char *driver);
+
+G_END_DECLS
+
+#endif	/* NM_DEVICE_INFINIBAND_H */
diff --git a/src/nm-device-wired.c b/src/nm-device-wired.c
new file mode 100644
index 0000000..d5c2878
--- /dev/null
+++ b/src/nm-device-wired.c
@@ -0,0 +1,547 @@
+/* -*- 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 (C) 2005 - 2011 Red Hat, Inc.
+ * Copyright (C) 2006 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+#include <glib.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_infiniband.h>
+#include <netinet/ether.h>
+
+#include "nm-device-wired.h"
+#include "nm-device-interface.h"
+#include "nm-device-private.h"
+#include "nm-dhcp-manager.h"
+#include "nm-logging.h"
+#include "nm-netlink-monitor.h"
+#include "nm-netlink-utils.h"
+#include "nm-system.h"
+#include "nm-utils.h"
+#include "NetworkManagerUtils.h"
+
+
+G_DEFINE_TYPE (NMDeviceWired, nm_device_wired, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIRED, NMDeviceWiredPrivate))
+
+#define NM_DEVICE_WIRED_LOG_LEVEL(dev) ((nm_device_get_device_type (dev) == NM_DEVICE_TYPE_INFINIBAND) ? LOGD_INFINIBAND : LOGD_ETHER)
+
+typedef struct {
+	guint8              hw_addr[NM_UTILS_HWADDR_LEN_MAX];         /* Currently set MAC address */
+	guint               hw_addr_type;
+	guint               hw_addr_len;
+	gboolean            carrier;
+
+	NMNetlinkMonitor *  monitor;
+	gulong              link_connected_id;
+	gulong              link_disconnected_id;
+	guint               carrier_action_defer_id;
+
+} NMDeviceWiredPrivate;
+
+static void
+carrier_action_defer_clear (NMDeviceWired *self)
+{
+	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
+
+	if (priv->carrier_action_defer_id) {
+		g_source_remove (priv->carrier_action_defer_id);
+		priv->carrier_action_defer_id = 0;
+	}
+}
+
+static gboolean
+carrier_action_defer_cb (gpointer user_data)
+{
+	NMDeviceWired *self = NM_DEVICE_WIRED (user_data);
+	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
+	NMDeviceState state;
+
+	priv->carrier_action_defer_id = 0;
+
+	state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
+	if (state == NM_DEVICE_STATE_UNAVAILABLE) {
+		if (priv->carrier)
+			nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
+	} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
+		if (!priv->carrier)
+			nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
+	}
+
+	return FALSE;
+}
+
+static void
+set_carrier (NMDeviceWired *self,
+             const gboolean carrier,
+             const gboolean defer_action)
+{
+	NMDeviceWiredPrivate *priv;
+	NMDeviceState state;
+
+	g_return_if_fail (NM_IS_DEVICE (self));
+
+	priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
+	if (priv->carrier == carrier)
+		return;
+
+	/* Clear any previous deferred action */
+	carrier_action_defer_clear (self);
+
+	priv->carrier = carrier;
+	g_object_notify (G_OBJECT (self), "carrier");
+
+	state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
+	nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
+				 "(%s): carrier now %s (device state %d%s)",
+	             nm_device_get_iface (NM_DEVICE (self)),
+	             carrier ? "ON" : "OFF",
+	             state,
+	             defer_action ? ", deferring action for 4 seconds" : "");
+
+	if (defer_action)
+		priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self);
+	else
+		carrier_action_defer_cb (self);
+}
+
+static void
+carrier_on (NMNetlinkMonitor *monitor,
+            int idx,
+            gpointer user_data)
+{
+	NMDevice *device = NM_DEVICE (user_data);
+	NMDeviceWired *self = NM_DEVICE_WIRED (device);
+	guint32 caps;
+
+	/* Make sure signal is for us */
+	if (idx == nm_device_get_ifindex (device)) {
+		/* Ignore spurious netlink messages */
+		caps = nm_device_get_capabilities (device);
+		if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
+			return;
+
+		set_carrier (self, TRUE, FALSE);
+	}
+}
+
+static void
+carrier_off (NMNetlinkMonitor *monitor,
+             int idx,
+             gpointer user_data)
+{
+	NMDevice *device = NM_DEVICE (user_data);
+	NMDeviceWired *self = NM_DEVICE_WIRED (device);
+	guint32 caps;
+
+	/* Make sure signal is for us */
+	if (idx == nm_device_get_ifindex (device)) {
+		NMDeviceState state;
+		gboolean defer = FALSE;
+
+		/* Ignore spurious netlink messages */
+		caps = nm_device_get_capabilities (device);
+		if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
+			return;
+
+		/* Defer carrier-off event actions while connected by a few seconds
+		 * so that tripping over a cable, power-cycling a switch, or breaking
+		 * off the RJ45 locking tab isn't so catastrophic.
+		 */
+		state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
+		if (state > NM_DEVICE_STATE_DISCONNECTED)
+			defer = TRUE;
+
+		set_carrier (self, FALSE, defer);
+	}
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMDeviceWiredPrivate *priv;
+	NMDevice *self;
+	guint32 caps;
+
+	object = G_OBJECT_CLASS (nm_device_wired_parent_class)->constructor (type,
+	                                                                        n_construct_params,
+	                                                                        construct_params);
+	if (!object)
+		return NULL;
+
+	self = NM_DEVICE (object);
+	priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
+
+	nm_log_dbg (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
+				"(%s): kernel ifindex %d",
+	            nm_device_get_iface (NM_DEVICE (self)),
+	            nm_device_get_ifindex (NM_DEVICE (self)));
+
+	if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_ETHERNET) {
+		priv->hw_addr_type = ARPHRD_ETHER;
+		priv->hw_addr_len = ETH_ALEN;
+	} else if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_INFINIBAND) {
+		priv->hw_addr_type = ARPHRD_INFINIBAND;
+		priv->hw_addr_len = INFINIBAND_ALEN;
+	} else
+		g_assert_not_reached ();
+
+	caps = nm_device_get_capabilities (self);
+	if (caps & NM_DEVICE_CAP_CARRIER_DETECT) {
+		GError *error = NULL;
+		guint32 ifflags = 0;
+
+		/* Only listen to netlink for cards that support carrier detect */
+		priv->monitor = nm_netlink_monitor_get ();
+
+		priv->link_connected_id = g_signal_connect (priv->monitor, "carrier-on",
+		                                            G_CALLBACK (carrier_on),
+		                                            self);
+		priv->link_disconnected_id = g_signal_connect (priv->monitor, "carrier-off",
+		                                               G_CALLBACK (carrier_off),
+		                                               self);
+
+		/* Get initial link state */
+		if (!nm_netlink_monitor_get_flags_sync (priv->monitor,
+		                                        nm_device_get_ifindex (NM_DEVICE (self)),
+		                                        &ifflags,
+		                                        &error)) {
+			nm_log_warn (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
+			             "(%s): couldn't get initial carrier state: (%d) %s",
+			             nm_device_get_iface (NM_DEVICE (self)),
+			             error ? error->code : -1,
+			             (error && error->message) ? error->message : "unknown");
+			g_clear_error (&error);
+		} else
+			priv->carrier = !!(ifflags & IFF_LOWER_UP);
+
+		nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
+		             "(%s): carrier is %s",
+		             nm_device_get_iface (NM_DEVICE (self)),
+		             priv->carrier ? "ON" : "OFF");
+
+		/* Request link state again just in case an error occurred getting the
+		 * initial link state.
+		 */
+		if (!nm_netlink_monitor_request_status (priv->monitor, &error)) {
+			nm_log_warn (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
+			             "(%s): couldn't request carrier state: (%d) %s",
+			             nm_device_get_iface (NM_DEVICE (self)),
+			             error ? error->code : -1,
+			             (error && error->message) ? error->message : "unknown");
+			g_clear_error (&error);
+		}
+	} else {
+		nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
+		             "(%s): driver '%s' does not support carrier detection.",
+		             nm_device_get_iface (self),
+		             nm_device_get_driver (self));
+		priv->carrier = TRUE;
+	}
+
+	return object;
+}
+
+static void
+nm_device_wired_init (NMDeviceWired * self)
+{
+}
+
+static gboolean
+real_hw_is_up (NMDevice *device)
+{
+	return nm_system_iface_is_up (nm_device_get_ip_ifindex (device));
+}
+
+static gboolean
+real_hw_bring_up (NMDevice *dev, gboolean *no_firmware)
+{
+	return nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware);
+}
+
+static void
+real_hw_take_down (NMDevice *dev)
+{
+	nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL);
+}
+
+static void
+real_update_hw_address (NMDevice *dev)
+{
+	NMDeviceWired *self = NM_DEVICE_WIRED (dev);
+	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
+	struct rtnl_link *rtnl;
+	struct nl_addr *addr;
+
+	rtnl = nm_netlink_index_to_rtnl_link (nm_device_get_ip_ifindex (dev));
+	if (!rtnl) {
+		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
+					"(%s) failed to read hardware address (error %d)",
+					nm_device_get_iface (dev), errno);
+		return;
+	}
+
+	addr = rtnl_link_get_addr (rtnl);
+	if (!addr) {
+		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
+					"(%s) no hardware address?",
+					nm_device_get_iface (dev));
+		rtnl_link_put (rtnl);
+		return;
+	}
+
+	if (nl_addr_get_len (addr) != priv->hw_addr_len) {
+		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
+					"(%s) hardware address is wrong length (expected %d got %d)",
+					nm_device_get_iface (dev),
+					priv->hw_addr_len, nl_addr_get_len (addr));
+ 	} else {
+		memcpy (&priv->hw_addr, nl_addr_get_binary_addr (addr),
+				priv->hw_addr_len);
+	}
+
+	rtnl_link_put (rtnl);
+}
+
+static gboolean
+real_can_interrupt_activation (NMDevice *dev)
+{
+	NMDeviceWired *self = NM_DEVICE_WIRED (dev);
+	gboolean interrupt = FALSE;
+
+	/* Devices that support carrier detect can interrupt activation
+	 * if the link becomes inactive.
+	 */
+	if (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_CARRIER_DETECT) {
+		if (NM_DEVICE_WIRED_GET_PRIVATE (self)->carrier == FALSE)
+			interrupt = TRUE;
+	}
+	return interrupt;
+}
+
+static gboolean
+real_is_available (NMDevice *dev)
+{
+	NMDeviceWired *self = NM_DEVICE_WIRED (dev);
+
+	/* Can't do anything if there isn't a carrier */
+	if (!NM_DEVICE_WIRED_GET_PRIVATE (self)->carrier)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+ip4_match_config (NMDevice *self, NMConnection *connection)
+{
+	NMSettingIP4Config *s_ip4;
+	int i, num;
+	GSList *leases, *iter;
+	NMDHCPManager *dhcp_mgr;
+	const char *method;
+
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	if (!s_ip4)
+		return FALSE;
+
+	/* Get any saved leases that apply to this connection */
+	dhcp_mgr = nm_dhcp_manager_get ();
+	leases = nm_dhcp_manager_get_lease_config (dhcp_mgr,
+	                                           nm_device_get_iface (self),
+	                                           nm_connection_get_uuid (connection));
+	g_object_unref (dhcp_mgr);
+
+	method = nm_setting_ip4_config_get_method (s_ip4);
+	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+		gboolean found = FALSE;
+
+		/* Find at least one lease's address on the device */
+		for (iter = leases; iter; iter = g_slist_next (iter)) {
+			NMIP4Config *ip4_config = iter->data;
+			NMIP4Address *addr = nm_ip4_config_get_address (ip4_config, 0);
+			struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) };
+
+			if (addr && nm_netlink_find_address (nm_device_get_ip_ifindex (self),
+			                                     AF_INET,
+			                                     &tmp,
+			                                     nm_ip4_address_get_prefix (addr))) {
+				found = TRUE; /* Yay, device has same address as a lease */
+				break;
+			}
+		}
+		g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
+		g_slist_free (leases);
+		return found;
+	} else {
+		/* Maybe the connection used to be DHCP and there are stale leases; ignore them */
+		g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
+		g_slist_free (leases);
+	}
+
+	/* 'shared' and 'link-local' aren't supported methods because 'shared'
+	 * requires too much iptables and dnsmasq state to be reclaimed, and
+	 * avahi-autoipd isn't smart enough to allow the link-local address to be
+	 * determined at any point other than when it was first assigned.
+	 */
+	if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
+		return FALSE;
+
+	/* Everything below for static addressing */
+
+	/* Find all IP4 addresses of this connection on the device */
+	num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+	for (i = 0; i < num; i++) {
+		NMIP4Address *addr = nm_setting_ip4_config_get_address (s_ip4, i);
+		struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) };
+
+		if (!nm_netlink_find_address (nm_device_get_ip_ifindex (self),
+		                              AF_INET,
+		                              &tmp,
+		                              nm_ip4_address_get_prefix (addr)))
+			return FALSE;
+	}
+
+	/* Success; all the connection's static IP addresses are assigned to the device */
+	return TRUE;
+}
+
+static NMConnection *
+connection_match_config (NMDevice *self, const GSList *connections)
+{
+	const GSList *iter;
+
+	for (iter = connections; iter; iter = iter->next) {
+		NMConnection *candidate = NM_CONNECTION (iter->data);
+
+		if (!ip4_match_config (self, candidate))
+			continue;
+
+		return candidate;
+	}
+
+	return NULL;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceWired *self = NM_DEVICE_WIRED (object);
+	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
+
+	if (priv->link_connected_id) {
+		g_signal_handler_disconnect (priv->monitor, priv->link_connected_id);
+		priv->link_connected_id = 0;
+	}
+	if (priv->link_disconnected_id) {
+		g_signal_handler_disconnect (priv->monitor, priv->link_disconnected_id);
+		priv->link_disconnected_id = 0;
+	}
+
+	carrier_action_defer_clear (self);
+
+	if (priv->monitor) {
+		g_object_unref (priv->monitor);
+		priv->monitor = NULL;
+	}
+
+	G_OBJECT_CLASS (nm_device_wired_parent_class)->dispose (object);
+}
+
+static void
+nm_device_wired_class_init (NMDeviceWiredClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (NMDeviceWiredPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->dispose = dispose;
+
+	parent_class->hw_is_up = real_hw_is_up;
+	parent_class->hw_bring_up = real_hw_bring_up;
+	parent_class->hw_take_down = real_hw_take_down;
+	parent_class->can_interrupt_activation = real_can_interrupt_activation;
+	parent_class->update_hw_address = real_update_hw_address;
+	parent_class->is_available = real_is_available;
+	parent_class->connection_match_config = connection_match_config;
+}
+
+/**
+ * nm_device_wired_get_hwaddr:
+ * @dev: an #NMDeviceWired
+ *
+ * Get a device's hardware address
+ *
+ * Return value: (transfer none): @dev's hardware address
+ */
+guint8 *
+nm_device_wired_get_hwaddr (NMDeviceWired *dev)
+{
+	NMDeviceWiredPrivate *priv;
+
+	g_return_val_if_fail (dev != NULL, NULL);
+
+	priv = NM_DEVICE_WIRED_GET_PRIVATE (dev);
+	return priv->hw_addr;
+}
+
+/**
+ * nm_device_wired_get_hwaddr_type:
+ * @dev: an #NMDeviceWired
+ *
+ * Get the type of a device's hardware address
+ *
+ * Return value: the type of @dev's hardware address
+ */
+int
+nm_device_wired_get_hwaddr_type (NMDeviceWired *dev)
+{
+	NMDeviceWiredPrivate *priv;
+
+	g_return_val_if_fail (dev != NULL, -1);
+
+	priv = NM_DEVICE_WIRED_GET_PRIVATE (dev);
+	return priv->hw_addr_type;
+}
+
+/**
+ * nm_device_wired_get_carrier:
+ * @dev: an #NMDeviceWired
+ *
+ * Get @dev's carrier status
+ *
+ * Return value: @dev's carrier
+ */
+gboolean
+nm_device_wired_get_carrier (NMDeviceWired *dev)
+{
+	NMDeviceWiredPrivate *priv;
+
+	g_return_val_if_fail (dev != NULL, -1);
+
+	priv = NM_DEVICE_WIRED_GET_PRIVATE (dev);
+	return priv->carrier;
+}
diff --git a/src/nm-device-wired.h b/src/nm-device-wired.h
new file mode 100644
index 0000000..b2f6ee4
--- /dev/null
+++ b/src/nm-device-wired.h
@@ -0,0 +1,55 @@
+/* -*- 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 (C) 2005 - 2010 Red Hat, Inc.
+ * Copyright (C) 2006 - 2008 Novell, Inc.
+ */
+
+#ifndef NM_DEVICE_WIRED_H
+#define NM_DEVICE_WIRED_H
+
+#include <glib-object.h>
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_WIRED			(nm_device_wired_get_type ())
+#define NM_DEVICE_WIRED(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIRED, NMDeviceWired))
+#define NM_DEVICE_WIRED_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_DEVICE_WIRED, NMDeviceWiredClass))
+#define NM_IS_DEVICE_WIRED(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIRED))
+#define NM_IS_DEVICE_WIRED_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_DEVICE_WIRED))
+#define NM_DEVICE_WIRED_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_DEVICE_WIRED, NMDeviceWiredClass))
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceWired;
+
+typedef struct {
+	NMDeviceClass parent;
+
+} NMDeviceWiredClass;
+
+GType nm_device_wired_get_type (void);
+
+guint8     *nm_device_wired_get_hwaddr      (NMDeviceWired *dev);
+int         nm_device_wired_get_hwaddr_type (NMDeviceWired *dev);
+gboolean    nm_device_wired_get_carrier     (NMDeviceWired *dev);
+
+G_END_DECLS
+
+#endif	/* NM_DEVICE_WIRED_H */
diff --git a/src/nm-device.c b/src/nm-device.c
index 95f07e4..45dae68 100644
--- a/src/nm-device.c
+++ b/src/nm-device.c
@@ -287,15 +287,6 @@ constructor (GType type,
 		goto error;
 	}
 
-	if (NM_DEVICE_GET_CLASS (dev)->update_hw_address)
-		NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev);
-
-	if (NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address)
-		NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address (dev);
-
-	if (NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address)
-		NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address (dev);
-
 	priv->dhcp_manager = nm_dhcp_manager_get ();
 
 	update_accept_ra_save (dev);
@@ -308,6 +299,24 @@ error:
 	return NULL;
 }
 
+static void
+constructed (GObject *object)
+{
+	NMDevice *dev = NM_DEVICE (object);
+
+	if (NM_DEVICE_GET_CLASS (dev)->update_hw_address)
+		NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev);
+
+	if (NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address)
+		NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address (dev);
+
+	if (NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address)
+		NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address (dev);
+
+	if (G_OBJECT_CLASS (nm_device_parent_class)->constructed)
+		G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
+}
+
 static gboolean
 nm_device_hw_is_up (NMDevice *self)
 {
@@ -3557,6 +3566,7 @@ nm_device_class_init (NMDeviceClass *klass)
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->constructor = constructor;
+	object_class->constructed = constructed;
 
 	klass->get_type_capabilities = real_get_type_capabilities;
 	klass->get_generic_capabilities = real_get_generic_capabilities;
diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c
index e8c6b82..4e45b9a 100644
--- a/src/nm-udev-manager.c
+++ b/src/nm-udev-manager.c
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
+#include <net/if_arp.h>
 
 #include "wireless-helper.h"
 
@@ -37,6 +38,7 @@
 #include "NetworkManagerUtils.h"
 #include "nm-device-wifi.h"
 #include "nm-device-olpc-mesh.h"
+#include "nm-device-infiniband.h"
 #include "nm-device-ethernet.h"
 #if WITH_WIMAX
 #include "nm-device-wimax.h"
@@ -388,6 +390,13 @@ is_wimax (const char *driver)
 	return g_strcmp0 (driver, "i2400m_usb") == 0;
 }
 
+static gboolean
+is_infiniband (GUdevDevice *device)
+{
+	gint etype = g_udev_device_get_sysfs_attr_as_int (device, "type");
+	return etype == ARPHRD_INFINIBAND;
+}
+
 static GObject *
 device_creator (NMUdevManager *manager,
                 GUdevDevice *udev_device,
@@ -452,7 +461,9 @@ device_creator (NMUdevManager *manager,
 #if WITH_WIMAX
 		device = (GObject *) nm_device_wimax_new (path, ifname, driver);
 #endif
-	} else
+	} else if (is_infiniband (udev_device))
+		device = (GObject *) nm_device_infiniband_new (path, ifname, driver);
+	else
 		device = (GObject *) nm_device_ethernet_new (path, ifname, driver);
 
 out:
@@ -486,7 +497,7 @@ net_add (NMUdevManager *self, GUdevDevice *device)
 	 * s390 CTC-type devices that report 256 for some reason.
 	 * FIXME: use something other than interface name to detect CTC here.
 	 */
-	if ((etype != 1) && (is_ctc == FALSE)) {
+	if ((etype != ARPHRD_ETHER) && (etype != ARPHRD_INFINIBAND) && (is_ctc == FALSE)) {
 		nm_log_dbg (LOGD_HW, "(%s): ignoring interface with type %d", iface, etype);
 		return;
 	}
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index f0bfc16..4a20d80 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -29,8 +29,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <gmodule.h>
-#include <net/ethernet.h>
-#include <netinet/ether.h>
+#include <net/if_arp.h>
 #include <pwd.h>
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib-lowlevel.h>
@@ -52,8 +51,9 @@
 #include <nm-setting-wired.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-wireless-security.h>
+#include <nm-utils.h>
 
-#include "../nm-device-ethernet.h"
+#include "../nm-device-wired.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-settings.h"
 #include "nm-settings-connection.h"
@@ -1179,6 +1179,7 @@ have_connection_for_device (NMSettings *self, GByteArray *mac)
 	gpointer data;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
+	NMSettingInfiniband *s_infiniband;
 	const GByteArray *setting_mac;
 	gboolean ret = FALSE;
 
@@ -1195,10 +1196,12 @@ have_connection_for_device (NMSettings *self, GByteArray *mac)
 		ctype = nm_setting_connection_get_connection_type (s_con);
 
 		if (   strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME)
+		    && strcmp (ctype, NM_SETTING_INFINIBAND_SETTING_NAME)
 		    && strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
 			continue;
 
 		s_wired = nm_connection_get_setting_wired (connection);
+		s_infiniband = nm_connection_get_setting_infiniband (connection);
 
 		/* No wired setting; therefore the PPPoE connection applies to any device */
 		if (!s_wired && !strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME)) {
@@ -1206,10 +1209,15 @@ have_connection_for_device (NMSettings *self, GByteArray *mac)
 			break;
 		}
 
-		setting_mac = nm_setting_wired_get_mac_address (s_wired);
+		g_assert (s_wired != NULL || s_infiniband != NULL);
+
+		setting_mac = s_wired ?
+			nm_setting_wired_get_mac_address (s_wired) :
+			nm_setting_infiniband_get_mac_address (s_infiniband);
 		if (setting_mac) {
 			/* A connection mac-locked to this device */
-			if (!memcmp (setting_mac->data, mac->data, ETH_ALEN)) {
+			if (mac->len == setting_mac->len &&
+				!memcmp (setting_mac->data, mac->data, mac->len)) {
 				ret = TRUE;
 				break;
 			}
@@ -1225,7 +1233,7 @@ have_connection_for_device (NMSettings *self, GByteArray *mac)
 
 /* Search through the list of blacklisted MAC addresses in the config file. */
 static gboolean
-is_mac_auto_wired_blacklisted (NMSettings *self, const GByteArray *mac)
+is_mac_auto_wired_blacklisted (NMSettings *self, const GByteArray *mac, int hwaddr_type)
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
 	GKeyFile *config;
@@ -1249,15 +1257,15 @@ is_mac_auto_wired_blacklisted (NMSettings *self, const GByteArray *mac)
 
 	list = g_key_file_get_string_list (config, "main", CONFIG_KEY_NO_AUTO_DEFAULT, NULL, NULL);
 	for (iter = list; iter && *iter; iter++) {
-		struct ether_addr *candidate;
+		guint8 *candidate, buffer[NM_UTILS_HWADDR_LEN_MAX];
 
-		if (strcmp(g_strstrip(*iter), "*") == 0) {
+		if (strcmp (g_strstrip (*iter), "*") == 0) {
 			found = TRUE;
 			break;
 		}
 
-		candidate = ether_aton (*iter);
-		if (candidate && !memcmp (mac->data, candidate->ether_addr_octet, ETH_ALEN)) {
+		candidate = nm_utils_hwaddr_aton (*iter, hwaddr_type, buffer);
+		if (candidate && !memcmp (mac->data, candidate, mac->len)) {
 			found = TRUE;
 			break;
 		}
@@ -1280,6 +1288,7 @@ default_wired_deleted (NMDefaultWiredConnection *wired,
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
 	NMSettingConnection *s_con;
+	int hwaddr_type;
 	char *tmp;
 	GKeyFile *config;
 	char **list, **iter, **updated;
@@ -1311,20 +1320,27 @@ default_wired_deleted (NMDefaultWiredConnection *wired,
 	if (!config)
 		goto cleanup;
 
+	if (nm_connection_get_setting_wired (NM_CONNECTION (wired)))
+		hwaddr_type = ARPHRD_ETHER;
+	else if (nm_connection_get_setting_infiniband (NM_CONNECTION (wired)))
+		hwaddr_type = ARPHRD_INFINIBAND;
+	else
+		goto cleanup;
+
 	g_key_file_set_list_separator (config, ',');
 	g_key_file_load_from_file (config, priv->config_file, G_KEY_FILE_KEEP_COMMENTS, NULL);
 
 	list = g_key_file_get_string_list (config, "main", CONFIG_KEY_NO_AUTO_DEFAULT, &len, NULL);
 	for (iter = list; iter && *iter; iter++) {
-		struct ether_addr *candidate;
+		guint8 *candidate, buffer[NM_UTILS_HWADDR_LEN_MAX];
 
-		if (strcmp(g_strstrip(*iter), "*") == 0) {
+		if (strcmp (g_strstrip (*iter), "*") == 0) {
 			found = TRUE;
 			break;
 		}
 
-		candidate = ether_aton (*iter);
-		if (candidate && !memcmp (mac->data, candidate->ether_addr_octet, ETH_ALEN)) {
+		candidate = nm_utils_hwaddr_aton (*iter, hwaddr_type, buffer);
+		if (candidate && !memcmp (mac->data, candidate, mac->len)) {
 			found = TRUE;
 			break;
 		}
@@ -1332,9 +1348,7 @@ default_wired_deleted (NMDefaultWiredConnection *wired,
 
 	/* Add this device's MAC to the list */
 	if (!found) {
-		tmp = g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x",
-		                       mac->data[0], mac->data[1], mac->data[2],
-		                       mac->data[3], mac->data[4], mac->data[5]);
+		tmp = nm_utils_hwaddr_ntoa (mac->data, hwaddr_type);
 
 		/* New list; size + 1 for the new element, + 1 again for ending NULL */
 		updated = g_malloc0 (sizeof (char*) * (len + 2));
@@ -1424,13 +1438,14 @@ nm_settings_device_added (NMSettings *self, NMDevice *device)
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
 	GByteArray *mac = NULL;
-	struct ether_addr tmp;
+	guint8 *hwaddr;
+	int hwaddr_type;
 	NMDefaultWiredConnection *wired;
 	gboolean read_only = TRUE;
 	const char *id;
 	char *defname;
 
-	if (nm_device_get_device_type (device) != NM_DEVICE_TYPE_ETHERNET)
+	if (!NM_IS_DEVICE_WIRED (device))
 		return;
 
 	/* If the device isn't managed or it already has a default wired connection,
@@ -1440,13 +1455,14 @@ nm_settings_device_added (NMSettings *self, NMDevice *device)
 	    || g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG))
 		return;
 
-	nm_device_ethernet_get_address (NM_DEVICE_ETHERNET (device), &tmp);
+	hwaddr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (device));
+	hwaddr_type = nm_device_wired_get_hwaddr_type (NM_DEVICE_WIRED (device));
 
-	mac = g_byte_array_sized_new (ETH_ALEN);
-	g_byte_array_append (mac, tmp.ether_addr_octet, ETH_ALEN);
+	mac = g_byte_array_new ();
+	g_byte_array_append (mac, hwaddr, nm_utils_hwaddr_len (hwaddr_type));
 
 	if (   have_connection_for_device (self, mac)
-	    || is_mac_auto_wired_blacklisted (self, mac))
+		|| is_mac_auto_wired_blacklisted (self, mac, hwaddr_type))
 		goto ignore;
 
 	if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS))
@@ -1480,7 +1496,7 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device)
 {
 	NMDefaultWiredConnection *connection;
 
-	if (nm_device_get_device_type (device) != NM_DEVICE_TYPE_ETHERNET)
+	if (!NM_IS_DEVICE_WIRED (device))
 		return;
 
 	connection = (NMDefaultWiredConnection *) g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG);
-- 
1.7.7

>From 749527c2c0456f8431cbe6631692d238c6d02626 Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Wed, 26 Oct 2011 09:43:05 -0400
Subject: [PATCH 6/7] libnm-glib: add NMDeviceInfiniband

---
 include/NetworkManager.h          |    1 +
 libnm-glib/Makefile.am            |    6 +
 libnm-glib/libnm-glib.ver         |    4 +
 libnm-glib/nm-device-infiniband.c |  308 +++++++++++++++++++++++++++++++++++++
 libnm-glib/nm-device-infiniband.h |   66 ++++++++
 libnm-glib/nm-device.c            |    4 +
 6 files changed, 389 insertions(+), 0 deletions(-)
 create mode 100644 libnm-glib/nm-device-infiniband.c
 create mode 100644 libnm-glib/nm-device-infiniband.h

diff --git a/include/NetworkManager.h b/include/NetworkManager.h
index 96803a0..2a3cfef 100644
--- a/include/NetworkManager.h
+++ b/include/NetworkManager.h
@@ -47,6 +47,7 @@
 #define NM_DBUS_INTERFACE_DHCP4_CONFIG      NM_DBUS_INTERFACE ".DHCP4Config"
 #define NM_DBUS_INTERFACE_IP6_CONFIG        NM_DBUS_INTERFACE ".IP6Config"
 #define NM_DBUS_INTERFACE_DHCP6_CONFIG      NM_DBUS_INTERFACE ".DHCP6Config"
+#define NM_DBUS_INTERFACE_DEVICE_INFINIBAND NM_DBUS_INTERFACE_DEVICE ".Infiniband"
 
 
 #define NM_DBUS_IFACE_SETTINGS            "org.freedesktop.NetworkManager.Settings"
diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am
index 4eec401..abee1f8 100644
--- a/libnm-glib/Makefile.am
+++ b/libnm-glib/Makefile.am
@@ -10,6 +10,7 @@ BUILT_SOURCES = \
 	nm-client-bindings.h \
 	nm-device-bindings.h \
 	nm-device-ethernet-bindings.h \
+	nm-device-infiniband-bindings.h \
 	nm-device-wifi-bindings.h \
 	nm-device-bt-bindings.h \
 	nm-settings-connection-bindings.h \
@@ -70,6 +71,7 @@ libnminclude_HEADERS = \
 	nm-client.h \
 	nm-device.h \
 	nm-device-ethernet.h \
+	nm-device-infiniband.h \
 	nm-device-wifi.h \
 	nm-device-bt.h \
 	nm-access-point.h \
@@ -98,6 +100,7 @@ libnm_glib_la_csources = \
 	nm-dbus-utils.c \
 	nm-device.c \
 	nm-device-ethernet.c \
+	nm-device-infiniband.c \
 	nm-device-wifi.c \
 	nm-device-bt.c \
 	nm-access-point.c \
@@ -189,6 +192,9 @@ nm-device-bindings.h: $(top_srcdir)/introspection/nm-device.xml
 nm-device-ethernet-bindings.h: $(top_srcdir)/introspection/nm-device-ethernet.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_ethernet --mode=glib-client --output=$@ $<
 
+nm-device-infiniband-bindings.h: $(top_srcdir)/introspection/nm-device-infiniband.xml
+	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_infiniband --mode=glib-client --output=$@ $<
+
 nm-device-wifi-bindings.h: $(top_srcdir)/introspection/nm-device-wifi.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-client --output=$@ $<
 
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
index 1a4a68c..9c2baf6 100644
--- a/libnm-glib/libnm-glib.ver
+++ b/libnm-glib/libnm-glib.ver
@@ -84,6 +84,10 @@ global:
 	nm_device_get_type;
 	nm_device_get_udi;
 	nm_device_get_vendor;
+	nm_device_infiniband_get_carrier;
+	nm_device_infiniband_get_hw_address;
+	nm_device_infiniband_get_type;
+	nm_device_infiniband_new;
 	nm_device_modem_get_current_capabilities;
 	nm_device_modem_get_modem_capabilities;
 	nm_device_modem_get_type;
diff --git a/libnm-glib/nm-device-infiniband.c b/libnm-glib/nm-device-infiniband.c
new file mode 100644
index 0000000..dc93cc9
--- /dev/null
+++ b/libnm-glib/nm-device-infiniband.c
@@ -0,0 +1,308 @@
+/* -*- 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 (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2011 Red Hat, Inc.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <linux/if_infiniband.h>
+#include <netinet/ether.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-infiniband.h>
+#include <nm-utils.h>
+
+#include "nm-device-infiniband.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+
+#include "nm-device-infiniband-bindings.h"
+
+G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	char *hw_address;
+	gboolean carrier;
+	gboolean carrier_valid;
+} NMDeviceInfinibandPrivate;
+
+enum {
+	PROP_0,
+	PROP_HW_ADDRESS,
+	PROP_CARRIER,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_HW_ADDRESS "HwAddress"
+#define DBUS_PROP_CARRIER "Carrier"
+
+/**
+ * nm_device_infiniband_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceInfiniband.
+ *
+ * Returns: (transfer full): a new device
+ **/
+GObject *
+nm_device_infiniband_new (DBusGConnection *connection, const char *path)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return g_object_new (NM_TYPE_DEVICE_INFINIBAND,
+	                     NM_OBJECT_DBUS_CONNECTION, connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
+}
+
+/**
+ * nm_device_infiniband_get_hw_address:
+ * @device: a #NMDeviceInfiniband
+ *
+ * Gets the hardware (MAC) address of the #NMDeviceInfiniband
+ *
+ * Returns: the hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_infiniband_get_hw_address (NMDeviceInfiniband *device)
+{
+	NMDeviceInfinibandPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), NULL);
+
+	priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device);
+	if (!priv->hw_address) {
+		priv->hw_address = _nm_object_get_string_property (NM_OBJECT (device),
+								   NM_DBUS_INTERFACE_DEVICE_INFINIBAND,
+								   DBUS_PROP_HW_ADDRESS,
+								   NULL);
+	}
+
+	return priv->hw_address;
+}
+
+/**
+ * nm_device_infiniband_get_carrier:
+ * @device: a #NMDeviceInfiniband
+ *
+ * Whether the device has carrier.
+ *
+ * Returns: %TRUE if the device has carrier
+ **/
+gboolean
+nm_device_infiniband_get_carrier (NMDeviceInfiniband *device)
+{
+	NMDeviceInfinibandPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), FALSE);
+
+	priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device);
+	if (!priv->carrier_valid) {
+		priv->carrier = _nm_object_get_boolean_property (NM_OBJECT (device),
+								 NM_DBUS_INTERFACE_DEVICE_INFINIBAND,
+								 DBUS_PROP_CARRIER,
+								 NULL);
+		priv->carrier_valid = TRUE;
+	}
+
+	return priv->carrier;
+}
+
+static gboolean
+connection_valid (NMDevice *device, NMConnection *connection)
+{
+	NMSettingConnection *s_con;
+	NMSettingInfiniband *s_infiniband;
+	const char *ctype, *hwaddr_str;
+	const GByteArray *mac;
+	guint8 *hwaddr, hwaddr_buf[INFINIBAND_ALEN];
+
+	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_INFINIBAND_SETTING_NAME) != 0)
+		return FALSE;
+
+	s_infiniband = nm_connection_get_setting_infiniband (connection);
+	if (!s_infiniband)
+		return FALSE;
+
+	hwaddr_str = nm_device_infiniband_get_hw_address (NM_DEVICE_INFINIBAND (device));
+	if (hwaddr_str) {
+		hwaddr = nm_utils_hwaddr_aton (hwaddr_str, ARPHRD_INFINIBAND, hwaddr_buf);
+		mac = nm_setting_infiniband_get_mac_address (s_infiniband);
+		if (mac && hwaddr && memcmp (mac->data, hwaddr, INFINIBAND_ALEN))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+/***********************************************************/
+
+static void
+nm_device_infiniband_init (NMDeviceInfiniband *device)
+{
+	NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device);
+
+	priv->carrier = FALSE;
+	priv->carrier_valid = FALSE;
+}
+
+static void
+register_for_property_changed (NMDeviceInfiniband *device)
+{
+	NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_DEVICE_INFINIBAND_HW_ADDRESS,           _nm_object_demarshal_generic, &priv->hw_address },
+		{ NM_DEVICE_INFINIBAND_CARRIER,              _nm_object_demarshal_generic, &priv->carrier },
+		{ NULL },
+	};
+
+	_nm_object_handle_properties_changed (NM_OBJECT (device),
+										  priv->proxy,
+										  property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMDeviceInfinibandPrivate *priv;
+
+	object = G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructor (type,
+																			  n_construct_params,
+																			  construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object);
+
+	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_INFINIBAND);
+
+	register_for_property_changed (NM_DEVICE_INFINIBAND (object));
+
+	return object;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object);
+
+	if (priv->proxy) {
+		g_object_unref (priv->proxy);
+		priv->proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (nm_device_infiniband_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object);
+
+	g_free (priv->hw_address);
+
+	G_OBJECT_CLASS (nm_device_infiniband_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceInfiniband *device = NM_DEVICE_INFINIBAND (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_infiniband_get_hw_address (device));
+		break;
+	case PROP_CARRIER:
+		g_value_set_boolean (value, nm_device_infiniband_get_carrier (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_infiniband_class_init (NMDeviceInfinibandClass *eth_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (eth_class);
+	NMDeviceClass *device_class = NM_DEVICE_CLASS (eth_class);
+
+	g_type_class_add_private (eth_class, sizeof (NMDeviceInfinibandPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+	object_class->get_property = get_property;
+	device_class->connection_valid = connection_valid;
+
+	/* properties */
+
+	/**
+	 * NMDeviceInfiniband:hw-address:
+	 *
+	 * The hardware (MAC) address of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_HW_ADDRESS,
+		 g_param_spec_string (NM_DEVICE_INFINIBAND_HW_ADDRESS,
+						  "Active MAC Address",
+						  "Currently set hardware MAC address",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	/**
+	 * NMDeviceInfiniband:carrier:
+	 *
+	 * Whether the device has carrier.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_INFINIBAND_CARRIER,
+					    "Carrier",
+					    "Carrier",
+					    FALSE,
+					    G_PARAM_READABLE));
+
+}
+
diff --git a/libnm-glib/nm-device-infiniband.h b/libnm-glib/nm-device-infiniband.h
new file mode 100644
index 0000000..ae87c5a
--- /dev/null
+++ b/libnm-glib/nm-device-infiniband.h
@@ -0,0 +1,66 @@
+/* -*- 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 (C) 2007 - 2008 Novell, Inc.
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_INFINIBAND_H
+#define NM_DEVICE_INFINIBAND_H
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_INFINIBAND            (nm_device_infiniband_get_type ())
+#define NM_DEVICE_INFINIBAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfiniband))
+#define NM_DEVICE_INFINIBAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass))
+#define NM_IS_DEVICE_INFINIBAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_INFINIBAND))
+#define NM_IS_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_INFINIBAND))
+#define NM_DEVICE_INFINIBAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass))
+
+#define NM_DEVICE_INFINIBAND_HW_ADDRESS  "hw-address"
+#define NM_DEVICE_INFINIBAND_CARRIER     "carrier"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceInfiniband;
+
+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);
+} NMDeviceInfinibandClass;
+
+GType nm_device_infiniband_get_type (void);
+
+GObject *nm_device_infiniband_new (DBusGConnection *connection, const char *path);
+
+const char * nm_device_infiniband_get_hw_address (NMDeviceInfiniband *device);
+gboolean     nm_device_infiniband_get_carrier (NMDeviceInfiniband *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_INFINIBAND_H */
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
index 1f9f367..91caca9 100644
--- a/libnm-glib/nm-device.c
+++ b/libnm-glib/nm-device.c
@@ -31,6 +31,7 @@
 #include "nm-device-modem.h"
 #include "nm-device-bt.h"
 #include "nm-device-wimax.h"
+#include "nm-device-infiniband.h"
 #include "nm-device.h"
 #include "nm-device-private.h"
 #include "nm-object-private.h"
@@ -811,6 +812,9 @@ nm_device_new (DBusGConnection *connection, const char *path)
 	case NM_DEVICE_TYPE_WIMAX:
 		dtype = NM_TYPE_DEVICE_WIMAX;
 		break;
+	case NM_DEVICE_TYPE_INFINIBAND:
+		dtype = NM_TYPE_DEVICE_INFINIBAND;
+		break;
 	default:
 		g_warning ("Unknown device type %d", g_value_get_uint (&value));
 		break;
-- 
1.7.7

>From 4e38f2d445f4d39c0792bbc80823b51140bc4ef4 Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Thu, 3 Nov 2011 11:04:38 -0400
Subject: [PATCH 7/7] Add IPoIB support to nmcli

---
 cli/src/connections.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 cli/src/devices.c     |    6 +++++
 2 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/cli/src/connections.c b/cli/src/connections.c
index 7d4fffc..4c61b9e 100644
--- a/cli/src/connections.c
+++ b/cli/src/connections.c
@@ -43,6 +43,7 @@
 #if WITH_WIMAX
 #include <nm-setting-wimax.h>
 #endif
+#include <nm-setting-infiniband.h>
 #include <nm-device-ethernet.h>
 #include <nm-device-wifi.h>
 #if WITH_WIMAX
@@ -51,8 +52,10 @@
 #include <nm-device-modem.h>
 #include <nm-device-bt.h>
 //#include <nm-device-olpc-mesh.h>
+#include <nm-device-infiniband.h>
 #include <nm-remote-settings.h>
 #include <nm-vpn-connection.h>
+#include <nm-utils.h>
 
 #include "utils.h"
 #include "settings.h"
@@ -958,6 +961,57 @@ check_modem_compatible (NMDeviceModem *device, NMConnection *connection, GError
 }
 
 static gboolean
+check_infiniband_compatible (NMDeviceInfiniband *device, NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingInfiniband *s_infiniband;
+	const char *connection_type;
+
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+
+	connection_type = nm_setting_connection_get_connection_type (s_con);
+	if (strcmp (connection_type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
+		g_set_error (error, 0, 0,
+		             "The connection was not an Infiniband connection.");
+		return FALSE;
+	}
+
+	s_infiniband = (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
+	if (!s_infiniband) {
+		g_set_error (error, 0, 0,
+		             "The connection was not a valid Infiniband connection.");
+		return FALSE;
+	}
+
+	if (s_infiniband) {
+		const GByteArray *mac;
+		const char *device_mac_str;
+		GByteArray *device_mac;
+
+		device_mac_str = nm_device_infiniband_get_hw_address (device);
+		device_mac = nm_utils_hwaddr_atoba (device_mac_str, ARPHRD_INFINIBAND);
+		if (!device_mac) {
+			g_set_error (error, 0, 0, "Invalid device MAC address.");
+			return FALSE;
+		}
+
+		mac = nm_setting_infiniband_get_mac_address (s_infiniband);
+		if (mac && memcmp (mac->data, device_mac->data, mac->len)) {
+			g_byte_array_unref (device_mac);
+			g_set_error (error, 0, 0,
+			             "The connection's MAC address did not match this device.");
+			return FALSE;
+		}
+		g_byte_array_unref (device_mac);
+	}
+
+	return TRUE;
+}
+
+static gboolean
 nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
 	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
@@ -977,6 +1031,8 @@ nm_device_is_connection_compatible (NMDevice *device, NMConnection *connection,
 #endif
 	else if (NM_IS_DEVICE_MODEM (device))
 		return check_modem_compatible (NM_DEVICE_MODEM (device), connection, error);
+	else if (NM_IS_DEVICE_INFINIBAND (device))
+		return check_infiniband_compatible (NM_DEVICE_INFINIBAND (device), connection, error);
 
 	g_set_error (error, 0, 0, "unhandled device type '%s'", G_OBJECT_TYPE_NAME (device));
 	return FALSE;
diff --git a/cli/src/devices.c b/cli/src/devices.c
index 0b19edb..3d46afe 100644
--- a/cli/src/devices.c
+++ b/cli/src/devices.c
@@ -41,6 +41,7 @@
 #if WITH_WIMAX
 #include <nm-device-wimax.h>
 #endif
+#include <nm-device-infiniband.h>
 #include <nm-utils.h>
 #include <nm-setting-ip4-config.h>
 #include <nm-setting-ip6-config.h>
@@ -56,6 +57,7 @@
 #if WITH_WIMAX
 #include <nm-setting-wimax.h>
 #endif
+#include <nm-setting-infiniband.h>
 
 #include "utils.h"
 #include "devices.h"
@@ -327,6 +329,8 @@ device_type_to_string (NMDevice *device)
 	case NM_DEVICE_TYPE_WIMAX:
 		return NM_SETTING_WIMAX_SETTING_NAME;
 #endif
+	case NM_DEVICE_TYPE_INFINIBAND:
+		return NM_SETTING_INFINIBAND_SETTING_NAME;
 	default:
 		return _("Unknown");
 	}
@@ -640,6 +644,8 @@ show_device_info (gpointer data, gpointer user_data)
 			else if (NM_IS_DEVICE_WIMAX (device))
 				hwaddr = nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device));
 #endif
+			else if (NM_IS_DEVICE_INFINIBAND (device))
+				hwaddr = nm_device_infiniband_get_hw_address (NM_DEVICE_INFINIBAND (device));
 
 			nmc->allowed_fields[0].value = nmc_fields_dev_list_sections[0].name;  /* "GENERAL"*/
 			nmc->allowed_fields[1].value = nm_device_get_iface (device);
-- 
1.7.7



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]