[PATCH] libnm-glib: add errors to device classes



The patch adds errors to libnm-glib's device classes.
The errors are returned in nm-device_connection_valid(dev,con,error) when
the device and connection don't match.

Currently, the error is not used. But it could be useful for nmcli and
elsewere.

Jirka
>From 2327759f2b4a8dd7c5c3a7b0c7d1e0ea6ff5cfbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= <jklimes redhat com>
Date: Wed, 14 Mar 2012 14:10:03 +0100
Subject: [PATCH] libnm-glib: add errors to device classes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Use the errors in nm_devive_valid_connection() to indicate why the connection
didn't match the device.

Signed-off-by: Jiří Klimeš <jklimes redhat com>
---
 cli/src/connections.c             |    4 +-
 libnm-glib/libnm-glib.ver         |   18 ++++++++++++
 libnm-glib/nm-device-bond.c       |   39 +++++++++++++++++++++++----
 libnm-glib/nm-device-bond.h       |   20 ++++++++++++-
 libnm-glib/nm-device-bt.c         |   48 +++++++++++++++++++++++++++++----
 libnm-glib/nm-device-bt.h         |   23 +++++++++++++++-
 libnm-glib/nm-device-ethernet.c   |   43 ++++++++++++++++++++++++++---
 libnm-glib/nm-device-ethernet.h   |   21 ++++++++++++++-
 libnm-glib/nm-device-infiniband.c |   44 ++++++++++++++++++++++++++----
 libnm-glib/nm-device-infiniband.h |   22 ++++++++++++++-
 libnm-glib/nm-device-modem.c      |   35 +++++++++++++++++++++---
 libnm-glib/nm-device-modem.h      |   19 ++++++++++++-
 libnm-glib/nm-device-olpc-mesh.c  |   31 +++++++++++++++++++--
 libnm-glib/nm-device-olpc-mesh.h  |   15 ++++++++++
 libnm-glib/nm-device-vlan.c       |   44 +++++++++++++++++++++++++-----
 libnm-glib/nm-device-vlan.h       |   22 ++++++++++++++-
 libnm-glib/nm-device-wifi.c       |   53 ++++++++++++++++++++++++++++++++-----
 libnm-glib/nm-device-wifi.h       |   27 ++++++++++++++++++-
 libnm-glib/nm-device-wimax.c      |   43 ++++++++++++++++++++++++++---
 libnm-glib/nm-device-wimax.h      |   21 ++++++++++++++-
 libnm-glib/nm-device.c            |    7 +++--
 libnm-glib/nm-device.h            |    6 +++-
 22 files changed, 538 insertions(+), 67 deletions(-)

diff --git a/cli/src/connections.c b/cli/src/connections.c
index 6dfd613..44ffed4 100644
--- a/cli/src/connections.c
+++ b/cli/src/connections.c
@@ -1233,11 +1233,11 @@ find_device_for_connection (NmCli *nmc,
 			if (iface) {
 				const char *dev_iface = nm_device_get_iface (dev);
 				if (   !strcmp (dev_iface, iface)
-				    && nm_device_connection_valid (dev, connection)) {
+				    && nm_device_connection_valid (dev, connection, NULL)) {
 					found_device = dev;
 				}
 			} else {
-				if (nm_device_connection_valid (dev, connection)) {
+				if (nm_device_connection_valid (dev, connection, NULL)) {
 					found_device = dev;
 				}
 			}
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
index 00fc3dd..7cb3b37 100644
--- a/libnm-glib/libnm-glib.ver
+++ b/libnm-glib/libnm-glib.ver
@@ -58,10 +58,14 @@ global:
 	nm_client_wwan_get_enabled;
 	nm_client_wwan_hardware_get_enabled;
 	nm_client_wwan_set_enabled;
+	nm_device_bond_error_get_type;
+	nm_device_bond_error_quark;
 	nm_device_bond_get_carrier;
 	nm_device_bond_get_hw_address;
 	nm_device_bond_get_type;
 	nm_device_bond_new;
+	nm_device_bt_error_get_type;
+	nm_device_bt_error_quark;
 	nm_device_bt_get_capabilities;
 	nm_device_bt_get_hw_address;
 	nm_device_bt_get_name;
@@ -69,6 +73,8 @@ global:
 	nm_device_bt_new;
 	nm_device_connection_valid;
 	nm_device_disconnect;
+	nm_device_ethernet_error_get_type;
+	nm_device_ethernet_error_quark;
 	nm_device_ethernet_get_carrier;
 	nm_device_ethernet_get_hw_address;
 	nm_device_ethernet_get_permanent_hw_address;
@@ -94,24 +100,34 @@ global:
 	nm_device_get_type;
 	nm_device_get_udi;
 	nm_device_get_vendor;
+	nm_device_infiniband_error_get_type;
+	nm_device_infiniband_error_quark;
 	nm_device_infiniband_get_carrier;
 	nm_device_infiniband_get_hw_address;
 	nm_device_infiniband_get_type;
 	nm_device_infiniband_new;
+	nm_device_modem_error_get_type;
+	nm_device_modem_error_quark;
 	nm_device_modem_get_current_capabilities;
 	nm_device_modem_get_modem_capabilities;
 	nm_device_modem_get_type;
 	nm_device_new;
+	nm_device_olpc_mesh_error_get_type;
+	nm_device_olpc_mesh_error_quark;
 	nm_device_olpc_mesh_get_active_channel;
 	nm_device_olpc_mesh_get_companion;
 	nm_device_olpc_mesh_get_hw_address;
 	nm_device_olpc_mesh_get_type;
 	nm_device_olpc_mesh_new;
+	nm_device_vlan_error_get_type;
+	nm_device_vlan_error_quark;
 	nm_device_vlan_get_carrier;
 	nm_device_vlan_get_hw_address;
 	nm_device_vlan_get_type;
 	nm_device_vlan_get_vlan_id;
 	nm_device_vlan_new;
+	nm_device_wifi_error_get_type;
+	nm_device_wifi_error_quark;
 	nm_device_wifi_get_access_point_by_path;
 	nm_device_wifi_get_access_points;
 	nm_device_wifi_get_active_access_point;
@@ -122,6 +138,8 @@ global:
 	nm_device_wifi_get_permanent_hw_address;
 	nm_device_wifi_get_type;
 	nm_device_wifi_new;
+	nm_device_wimax_error_get_type;
+	nm_device_wimax_error_quark;
 	nm_device_wimax_get_active_nsp;
 	nm_device_wimax_get_bsid;
 	nm_device_wimax_get_center_frequency;
diff --git a/libnm-glib/nm-device-bond.c b/libnm-glib/nm-device-bond.c
index 411dfdb..5a9b9e5 100644
--- a/libnm-glib/nm-device-bond.c
+++ b/libnm-glib/nm-device-bond.c
@@ -17,8 +17,7 @@
  * 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.
+ * Copyright (C) 2012 Red Hat, Inc.
  */
 
 #include <config.h>
@@ -56,6 +55,23 @@ enum {
 #define DBUS_PROP_CARRIER "Carrier"
 
 /**
+ * nm_device_bond_error_quark:
+ *
+ * Registers an error quark for #NMDeviceBond if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceBond errors.
+ **/
+GQuark
+nm_device_bond_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-bond-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_bond_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -116,27 +132,38 @@ nm_device_bond_get_carrier (NMDeviceBond *device)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingBond *s_bond;
 	const char *ctype, *dev_iface_name, *bond_iface_name;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_BOND_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_BOND_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION,
+		             "The connection was not a bond connection.");
 		return FALSE;
+	}
 
 	s_bond = nm_connection_get_setting_bond (connection);
-	if (!s_bond)
+	if (!s_bond) {
+		g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION,
+		             "The connection was not a valid bond connection.");
 		return FALSE;
+	}
 
 	dev_iface_name = nm_device_get_iface (device);
 	bond_iface_name = nm_setting_bond_get_interface_name (s_bond);
-	if (g_strcmp0 (dev_iface_name, bond_iface_name) != 0)
+	if (g_strcmp0 (dev_iface_name, bond_iface_name) != 0) {
+		g_set_error (error, NM_DEVICE_BOND_ERROR, NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH,
+		             "The interfaces of the device and the connection didn't match.");
 		return FALSE;
+	}
 
 	/* FIXME: check slaves? But we can't... */
 
diff --git a/libnm-glib/nm-device-bond.h b/libnm-glib/nm-device-bond.h
index 097a204..db4a90f 100644
--- a/libnm-glib/nm-device-bond.h
+++ b/libnm-glib/nm-device-bond.h
@@ -17,8 +17,7 @@
  * 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.
+ * Copyright (C) 2012 Red Hat, Inc.
  */
 
 #ifndef NM_DEVICE_BOND_H
@@ -35,6 +34,23 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_BOND))
 #define NM_DEVICE_BOND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBondClass))
 
+/**
+ * NMDeviceBondError:
+ * @NM_DEVICE_BOND_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION: the connection was not of bond type
+ * @NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION: the bond connection was invalid
+ * @NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH: the interfaces of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_BOND_ERROR_UNKNOWN = 0,             /*< nick=UnknownError >*/
+	NM_DEVICE_BOND_ERROR_NOT_BOND_CONNECTION,     /*< nick=NotBondConnection >*/
+	NM_DEVICE_BOND_ERROR_INVALID_BOND_CONNECTION, /*< nick=InvalidBondConnection >*/
+	NM_DEVICE_BOND_ERROR_INTERFACE_MISMATCH,      /*< nick=InterfaceMismatch >*/
+} NMDeviceBondError;
+
+#define NM_DEVICE_BOND_ERROR nm_device_bond_error_quark ()
+GQuark nm_device_bond_error_quark (void);
+
 #define NM_DEVICE_BOND_HW_ADDRESS  "hw-address"
 #define NM_DEVICE_BOND_CARRIER     "carrier"
 
diff --git a/libnm-glib/nm-device-bt.c b/libnm-glib/nm-device-bt.c
index 8541970..1dcee0e 100644
--- a/libnm-glib/nm-device-bt.c
+++ b/libnm-glib/nm-device-bt.c
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2011 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #include <config.h>
@@ -60,6 +60,23 @@ enum {
 #define DBUS_PROP_BT_CAPABILITIES "BtCapabilities"
 
 /**
+ * nm_device_bt_error_quark:
+ *
+ * Registers an error quark for #NMDeviceBt if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceBt errors.
+ **/
+GQuark
+nm_device_bt_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-bt-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_bt_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -154,7 +171,7 @@ get_connection_bt_type (NMConnection *connection)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingBluetooth *s_bt;
@@ -165,30 +182,49 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	NMBluetoothCapabilities dev_caps;
 	NMBluetoothCapabilities bt_type;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_BLUETOOTH_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_BLUETOOTH_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION,
+		             "The connection was not a Bluetooth connection.");
 		return FALSE;
+	}
 
 	s_bt = nm_connection_get_setting_bluetooth (connection);
-	if (!s_bt)
+	if (!s_bt) {
+		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION,
+		             "The connection was not a valid Bluetooth connection.");
 		return FALSE;
+	}
 
 	/* Check BT address */
 	hw_str = nm_device_bt_get_hw_address (NM_DEVICE_BT (device));
 	if (hw_str) {
 		hw_mac = ether_aton (hw_str);
+		if (!hw_mac) {
+			g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC,
+			             "Invalid device MAC address.");
+			return FALSE;
+		}
 		mac = nm_setting_bluetooth_get_bdaddr (s_bt);
-		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) {
+			g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_MAC_MISMATCH,
+			             "The MACs of the device and the connection didn't match.");
 			return FALSE;
+		}
 	}
 
 	dev_caps = nm_device_bt_get_capabilities (NM_DEVICE_BT (device));
 	bt_type = get_connection_bt_type (connection);
-	if (!(bt_type & dev_caps))
+	if (!(bt_type & dev_caps)) {
+		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS,
+		             "The device missed BT capabilities required by the connection.");
 		return FALSE;
+	}
 
 	return TRUE;
 }
diff --git a/libnm-glib/nm-device-bt.h b/libnm-glib/nm-device-bt.h
index 71817f8..8f9a78a 100644
--- a/libnm-glib/nm-device-bt.h
+++ b/libnm-glib/nm-device-bt.h
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2008 - 2009 Red Hat, Inc.
+ * Copyright (C) 2008 - 2012 Red Hat, Inc.
  * Copyright (C) 2008 Novell, Inc.
  */
 
@@ -36,6 +36,27 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_BT))
 #define NM_DEVICE_BT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BT, NMDeviceBtClass))
 
+/**
+ * NMDeviceBtError:
+ * @NM_DEVICE_BT_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION: the connection was not of bluetooth type
+ * @NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION: the bluetooth connection was invalid
+ * @NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_BT_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ * @NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS: the device missed required capabilities
+ */
+typedef enum {
+	NM_DEVICE_BT_ERROR_UNKNOWN = 0,           /*< nick=UnknownError >*/
+	NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION,     /*< nick=NotBtConnection >*/
+	NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION, /*< nick=InvalidBtConnection >*/
+	NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC,    /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_BT_ERROR_MAC_MISMATCH,          /*< nick=MacMismatch >*/
+	NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS,   /*< nick=MissingDeviceCaps >*/
+} NMDeviceBtError;
+
+#define NM_DEVICE_BT_ERROR nm_device_bt_error_quark ()
+GQuark nm_device_bt_error_quark (void);
+
 #define NM_DEVICE_BT_HW_ADDRESS   "hw-address"
 #define NM_DEVICE_BT_NAME         "name"
 #define NM_DEVICE_BT_CAPABILITIES "bt-capabilities"
diff --git a/libnm-glib/nm-device-ethernet.c b/libnm-glib/nm-device-ethernet.c
index b062692..d29fe4e 100644
--- a/libnm-glib/nm-device-ethernet.c
+++ b/libnm-glib/nm-device-ethernet.c
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2011 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #include <config.h>
@@ -64,6 +64,23 @@ enum {
 #define DBUS_PROP_CARRIER "Carrier"
 
 /**
+ * nm_device_ethernet_error_quark:
+ *
+ * Registers an error quark for #NMDeviceEthernet if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceEthernet errors.
+ **/
+GQuark
+nm_device_ethernet_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-ethernet-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_ethernet_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -159,26 +176,34 @@ nm_device_ethernet_get_carrier (NMDeviceEthernet *device)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	const char *ctype;
 	gboolean is_pppoe = FALSE;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_PPPOE_SETTING_NAME))
 		is_pppoe = TRUE;
-	else if (strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME) != 0)
+	else if (strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_ETHERNET_ERROR, NM_DEVICE_ETHERNET_ERROR_NOT_ETHERNET_CONNECTION,
+		             "The connection was not a wired or PPPoE connection.");
 		return FALSE;
+	}
 
 	s_wired = nm_connection_get_setting_wired (connection);
 	/* Wired setting optional for PPPoE */
-	if (!is_pppoe && !s_wired)
+	if (!is_pppoe && !s_wired) {
+		g_set_error (error, NM_DEVICE_ETHERNET_ERROR, NM_DEVICE_ETHERNET_ERROR_INVALID_ETHERNET_CONNECTION,
+		             "The connection was not a valid ethernet connection.");
 		return FALSE;
+	}
 
 	if (s_wired) {
 		const GByteArray *mac;
@@ -191,9 +216,17 @@ connection_valid (NMDevice *device, NMConnection *connection)
 		perm_str = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device));
 		if (perm_str) {
 			perm_mac = ether_aton (perm_str);
+			if (!perm_mac) {
+				g_set_error (error, NM_DEVICE_ETHERNET_ERROR, NM_DEVICE_ETHERNET_ERROR_INVALID_DEVICE_MAC,
+				             "Invalid device MAC address.");
+				return FALSE;
+			}
 			mac = nm_setting_wired_get_mac_address (s_wired);
-			if (mac && perm_mac && memcmp (mac->data, perm_mac->ether_addr_octet, ETH_ALEN))
+			if (mac && perm_mac && memcmp (mac->data, perm_mac->ether_addr_octet, ETH_ALEN)) {
+				g_set_error (error, NM_DEVICE_ETHERNET_ERROR, NM_DEVICE_ETHERNET_ERROR_MAC_MISMATCH,
+				             "The MACs of the device and the connection didn't match.");
 				return FALSE;
+			}
 		}
 	}
 
diff --git a/libnm-glib/nm-device-ethernet.h b/libnm-glib/nm-device-ethernet.h
index 305ca02..f14cd04 100644
--- a/libnm-glib/nm-device-ethernet.h
+++ b/libnm-glib/nm-device-ethernet.h
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #ifndef NM_DEVICE_ETHERNET_H
@@ -35,6 +35,25 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_ETHERNET))
 #define NM_DEVICE_ETHERNET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass))
 
+/**
+ * NMDeviceEthernetError:
+ * @NM_DEVICE_ETHERNET_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_ETHERNET_ERROR_NOT_ETHERNET_CONNECTION: the connection was not of ethernet or PPPoE type
+ * @NM_DEVICE_ETHERNET_ERROR_INVALID_ETHERNET_CONNECTION: the ethernet connection was invalid
+ * @NM_DEVICE_ETHERNET_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_ETHERNET_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_ETHERNET_ERROR_UNKNOWN = 0,                 /*< nick=UnknownError >*/
+	NM_DEVICE_ETHERNET_ERROR_NOT_ETHERNET_CONNECTION,     /*< nick=NotEthernetConnection >*/
+	NM_DEVICE_ETHERNET_ERROR_INVALID_ETHERNET_CONNECTION, /*< nick=InvalidEthernetConnection >*/
+	NM_DEVICE_ETHERNET_ERROR_INVALID_DEVICE_MAC,          /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_ETHERNET_ERROR_MAC_MISMATCH,                /*< nick=MacMismatch >*/
+} NMDeviceEthernetError;
+
+#define NM_DEVICE_ETHERNET_ERROR nm_device_ethernet_error_quark ()
+GQuark nm_device_ethernet_error_quark (void);
+
 #define NM_DEVICE_ETHERNET_HW_ADDRESS  "hw-address"
 #define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address"
 #define NM_DEVICE_ETHERNET_SPEED       "speed"
diff --git a/libnm-glib/nm-device-infiniband.c b/libnm-glib/nm-device-infiniband.c
index 941f171..ea95da1 100644
--- a/libnm-glib/nm-device-infiniband.c
+++ b/libnm-glib/nm-device-infiniband.c
@@ -17,8 +17,7 @@
  * 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.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  */
 
 #include <config.h>
@@ -57,6 +56,23 @@ enum {
 #define DBUS_PROP_CARRIER "Carrier"
 
 /**
+ * nm_device_infiniband_error_quark:
+ *
+ * Registers an error quark for #NMDeviceInfiniband if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceInfiniband errors.
+ **/
+GQuark
+nm_device_infiniband_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-infiniband-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_infiniband_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -117,7 +133,7 @@ nm_device_infiniband_get_carrier (NMDeviceInfiniband *device)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingInfiniband *s_infiniband;
@@ -125,23 +141,39 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	const GByteArray *mac;
 	guint8 *hwaddr, hwaddr_buf[INFINIBAND_ALEN];
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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)
+	if (strcmp (ctype, NM_SETTING_INFINIBAND_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_INFINIBAND_ERROR, NM_DEVICE_INFINIBAND_ERROR_NOT_INFINIBAND_CONNECTION,
+		             "The connection was not a InfiniBand connection.");
 		return FALSE;
+	}
 
 	s_infiniband = nm_connection_get_setting_infiniband (connection);
-	if (!s_infiniband)
+	if (!s_infiniband) {
+		g_set_error (error, NM_DEVICE_INFINIBAND_ERROR, NM_DEVICE_INFINIBAND_ERROR_INVALID_INFINIBAND_CONNECTION,
+		             "The connection was not a valid InfiniBand connection.");
 		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);
+		if (!hwaddr) {
+			g_set_error (error, NM_DEVICE_INFINIBAND_ERROR, NM_DEVICE_INFINIBAND_ERROR_INVALID_DEVICE_MAC,
+			             "Invalid device MAC address.");
+			return FALSE;
+		}
 		mac = nm_setting_infiniband_get_mac_address (s_infiniband);
-		if (mac && hwaddr && memcmp (mac->data, hwaddr, INFINIBAND_ALEN))
+		if (mac && hwaddr && memcmp (mac->data, hwaddr, INFINIBAND_ALEN)) {
+			g_set_error (error, NM_DEVICE_INFINIBAND_ERROR, NM_DEVICE_INFINIBAND_ERROR_MAC_MISMATCH,
+			             "The MACs of the device and the connection didn't match.");
 			return FALSE;
+		}
 	}
 
 	return TRUE;
diff --git a/libnm-glib/nm-device-infiniband.h b/libnm-glib/nm-device-infiniband.h
index 604a049..d0e754b 100644
--- a/libnm-glib/nm-device-infiniband.h
+++ b/libnm-glib/nm-device-infiniband.h
@@ -17,8 +17,7 @@
  * 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.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  */
 
 #ifndef NM_DEVICE_INFINIBAND_H
@@ -35,6 +34,25 @@ G_BEGIN_DECLS
 #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))
 
+/**
+ * NMDeviceInfinibandError:
+ * @NM_DEVICE_INFINIBAND_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_INFINIBAND_ERROR_NOT_INFINIBAND_CONNECTION: the connection was not of InfiniBand type
+ * @NM_DEVICE_INFINIBAND_ERROR_INVALID_INFINIBAND_CONNECTION: the InfiniBand connection was invalid
+ * @NM_DEVICE_INFINIBAND_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_INFINIBAND_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_INFINIBAND_ERROR_UNKNOWN = 0,                   /*< nick=UnknownError >*/
+	NM_DEVICE_INFINIBAND_ERROR_NOT_INFINIBAND_CONNECTION,     /*< nick=NotInfinibandConnection >*/
+	NM_DEVICE_INFINIBAND_ERROR_INVALID_INFINIBAND_CONNECTION, /*< nick=InvalidInfinibandConnection >*/
+	NM_DEVICE_INFINIBAND_ERROR_INVALID_DEVICE_MAC,            /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_INFINIBAND_ERROR_MAC_MISMATCH,                  /*< nick=MacMismatch >*/
+} NMDeviceInfinibandError;
+
+#define NM_DEVICE_INFINIBAND_ERROR nm_device_infiniband_error_quark ()
+GQuark nm_device_infiniband_error_quark (void);
+
 #define NM_DEVICE_INFINIBAND_HW_ADDRESS  "hw-address"
 #define NM_DEVICE_INFINIBAND_CARRIER     "carrier"
 
diff --git a/libnm-glib/nm-device-modem.c b/libnm-glib/nm-device-modem.c
index 87cc52f..e7d280f 100644
--- a/libnm-glib/nm-device-modem.c
+++ b/libnm-glib/nm-device-modem.c
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  * Copyright (C) 2008 Novell, Inc.
  */
 
@@ -59,6 +59,23 @@ enum {
 #define DBUS_PROP_CURRENT_CAPS "CurrentCapabilities"
 
 /**
+ * nm_device_modem_error_quark:
+ *
+ * Registers an error quark for #NMDeviceModem if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceModem errors.
+ **/
+GQuark
+nm_device_modem_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-modem-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_modem_get_modem_capabilities:
  * @self: a #NMDeviceModem
  *
@@ -100,7 +117,7 @@ nm_device_modem_get_current_capabilities (NMDeviceModem *self)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingGsm *s_gsm;
@@ -108,22 +125,32 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	const char *ctype;
 	NMDeviceModemCapabilities current_caps;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_GSM_SETTING_NAME) != 0
-	    && strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME) != 0)
+	    && strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_MODEM_ERROR, NM_DEVICE_MODEM_ERROR_NOT_MODEM_CONNECTION,
+		             "The connection was not a modem connection.");
 		return FALSE;
+	}
 
 	s_gsm = nm_connection_get_setting_gsm (connection);
 	s_cdma = nm_connection_get_setting_cdma (connection);
-	if (!s_cdma && !s_gsm)
+	if (!s_cdma && !s_gsm) {
+		g_set_error (error, NM_DEVICE_MODEM_ERROR, NM_DEVICE_MODEM_ERROR_INVALID_MODEM_CONNECTION,
+		             "The connection was not a valid modem connection.");
 		return FALSE;
+	}
 
 	current_caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
 	if (   !(s_gsm && (current_caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS))
 	    && !(s_cdma && (current_caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO))) {
+		g_set_error (error, NM_DEVICE_MODEM_ERROR, NM_DEVICE_MODEM_ERROR_MISSING_DEVICE_CAPS,
+		             "The device missed capabilities required by the GSM/CDMA connection.");
 		return FALSE;
 	}
 
diff --git a/libnm-glib/nm-device-modem.h b/libnm-glib/nm-device-modem.h
index bf84b90..6f9666d 100644
--- a/libnm-glib/nm-device-modem.h
+++ b/libnm-glib/nm-device-modem.h
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  * Copyright (C) 2008 Novell, Inc.
  */
 
@@ -35,6 +35,23 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_MODEM))
 #define NM_DEVICE_MODEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_MODEM, NMDeviceModemClass))
 
+/**
+ * NMDeviceModemError:
+ * @NM_DEVICE_MODEM_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_MODEM_ERROR_NOT_MODEM_CONNECTION: the connection was not of modem type
+ * @NM_DEVICE_MODEM_ERROR_INVALID_MODEM_CONNECTION: the modem connection was invalid
+ * @NM_DEVICE_MODEM_ERROR_MISSING_DEVICE_CAPS: the device missed required capabilities
+ */
+typedef enum {
+	NM_DEVICE_MODEM_ERROR_UNKNOWN = 0,              /*< nick=UnknownError >*/
+	NM_DEVICE_MODEM_ERROR_NOT_MODEM_CONNECTION,     /*< nick=NotModemConnection >*/
+	NM_DEVICE_MODEM_ERROR_INVALID_MODEM_CONNECTION, /*< nick=InvalidModemConnection >*/
+	NM_DEVICE_MODEM_ERROR_MISSING_DEVICE_CAPS,      /*< nick=MissingDeviceCaps >*/
+} NMDeviceModemError;
+
+#define NM_DEVICE_MODEM_ERROR nm_device_modem_error_quark ()
+GQuark nm_device_modem_error_quark (void);
+
 #define NM_DEVICE_MODEM_MODEM_CAPABILITIES   "modem-capabilities"
 #define NM_DEVICE_MODEM_CURRENT_CAPABILITIES "current-capabilities"
 
diff --git a/libnm-glib/nm-device-olpc-mesh.c b/libnm-glib/nm-device-olpc-mesh.c
index f4cdac7..a0e8cac 100644
--- a/libnm-glib/nm-device-olpc-mesh.c
+++ b/libnm-glib/nm-device-olpc-mesh.c
@@ -58,6 +58,23 @@ enum {
 #define DBUS_PROP_ACTIVE_CHANNEL  "ActiveChannel"
 
 /**
+ * nm_device_olpc_mesh_error_quark:
+ *
+ * Registers an error quark for #NMDeviceOlpcMesh if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceOlpcMesh errors.
+ **/
+GQuark
+nm_device_olpc_mesh_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-olpc-mesh-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_olpc_mesh_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -136,22 +153,30 @@ nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingOlpcMesh *s_olpc_mesh;
 	const char *ctype;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_OLPC_MESH_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_OLPC_MESH_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_OLPC_MESH_ERROR, NM_DEVICE_OLPC_MESH_ERROR_NOT_OLPC_MESH_CONNECTION,
+		             "The connection was not a Olpc Mesh connection.");
 		return FALSE;
+	}
 
 	s_olpc_mesh = nm_connection_get_setting_olpc_mesh (connection);
-	if (!s_olpc_mesh)
+	if (!s_olpc_mesh) {
+		g_set_error (error, NM_DEVICE_OLPC_MESH_ERROR, NM_DEVICE_OLPC_MESH_ERROR_INVALID_OLPC_MESH_CONNECTION,
+		             "The connection was not a valid Olpc Mesh connection.");
 		return FALSE;
+	}
 
 	return TRUE;
 }
diff --git a/libnm-glib/nm-device-olpc-mesh.h b/libnm-glib/nm-device-olpc-mesh.h
index 0b04b76..7945d0c 100644
--- a/libnm-glib/nm-device-olpc-mesh.h
+++ b/libnm-glib/nm-device-olpc-mesh.h
@@ -36,6 +36,21 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_OLPC_MESH))
 #define NM_DEVICE_OLPC_MESH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass))
 
+/**
+ * NMDeviceOlpcMeshError:
+ * @NM_DEVICE_OLPC_MESH_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_OLPC_MESH_ERROR_NOT_OLPC_MESH_CONNECTION: the connection was not of Olpc Mesh type
+ * @NM_DEVICE_OLPC_MESH_ERROR_INVALID_OLPC_MESH_CONNECTION: the Olpc Mesh connection was invalid
+ */
+typedef enum {
+	NM_DEVICE_OLPC_MESH_ERROR_UNKNOWN = 0,                  /*< nick=UnknownError >*/
+	NM_DEVICE_OLPC_MESH_ERROR_NOT_OLPC_MESH_CONNECTION,     /*< nick=NotOlpcMeshConnection >*/
+	NM_DEVICE_OLPC_MESH_ERROR_INVALID_OLPC_MESH_CONNECTION, /*< nick=InvalidOlpcMeshConnection >*/
+} NMDeviceOlpcMeshError;
+
+#define NM_DEVICE_OLPC_MESH_ERROR nm_device_olpc_mesh_error_quark ()
+GQuark nm_device_olpc_mesh_error_quark (void);
+
 #define NM_DEVICE_OLPC_MESH_HW_ADDRESS     "hw-address"
 #define NM_DEVICE_OLPC_MESH_COMPANION      "companion"
 #define NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL "active-channel"
diff --git a/libnm-glib/nm-device-vlan.c b/libnm-glib/nm-device-vlan.c
index dacb326..3195446 100644
--- a/libnm-glib/nm-device-vlan.c
+++ b/libnm-glib/nm-device-vlan.c
@@ -17,8 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2012 Red Hat, Inc.
+ * Copyright (C) 2012 Red Hat, Inc.
  */
 
 #include <config.h>
@@ -59,6 +58,23 @@ enum {
 #define DBUS_PROP_VLAN_ID "VlanId"
 
 /**
+ * nm_device_vlan_error_quark:
+ *
+ * Registers an error quark for #NMDeviceVlan if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceVlan errors.
+ **/
+GQuark
+nm_device_vlan_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-vlan-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_vlan_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -134,30 +150,44 @@ nm_device_vlan_get_vlan_id (NMDeviceVlan *device)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingVlan *s_vlan;
 	const char *ctype, *dev_iface_name, *vlan_iface_name;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_VLAN_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_VLAN_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION,
+		             "The connection was not a VLAN connection.");
 		return FALSE;
+	}
 
 	s_vlan = nm_connection_get_setting_vlan (connection);
-	if (!s_vlan)
+	if (!s_vlan) {
+		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION,
+		             "The connection was not a valid VLAN connection.");
 		return FALSE;
+	}
 
-	if (nm_setting_vlan_get_id (s_vlan) != nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device)))
+	if (nm_setting_vlan_get_id (s_vlan) != nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device))) {
+		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_ID_MISMATCH,
+		             "The VLAN identifiers of the device and the connection didn't match.");
 		return FALSE;
+	}
 
 	dev_iface_name = nm_device_get_iface (device);
 	vlan_iface_name = nm_setting_vlan_get_interface_name (s_vlan);
-	if (vlan_iface_name && g_strcmp0 (dev_iface_name, vlan_iface_name) != 0)
+	if (vlan_iface_name && g_strcmp0 (dev_iface_name, vlan_iface_name) != 0) {
+		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH,
+		             "The interfaces of the device and the connection didn't match.");
 		return FALSE;
+	}
 
 	return TRUE;
 }
diff --git a/libnm-glib/nm-device-vlan.h b/libnm-glib/nm-device-vlan.h
index d39effd..df02025 100644
--- a/libnm-glib/nm-device-vlan.h
+++ b/libnm-glib/nm-device-vlan.h
@@ -17,8 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2012 Red Hat, Inc.
+ * Copyright (C) 2012 Red Hat, Inc.
  */
 
 #ifndef NM_DEVICE_VLAN_H
@@ -35,6 +34,25 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_VLAN))
 #define NM_DEVICE_VLAN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass))
 
+/**
+ * NMDeviceVlanError:
+ * @NM_DEVICE_VLAN_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION: the connection was not of VLAN type
+ * @NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION: the VLAN connection was invalid
+ * @NM_DEVICE_VLAN_ERROR_ID_MISMATCH: the VLAN identifiers of the connection and the device mismatched
+ * @NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH: the interfaces of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_VLAN_ERROR_UNKNOWN = 0,             /*< nick=UnknownError >*/
+	NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION,     /*< nick=NotVlanConnection >*/
+	NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION, /*< nick=InvalidVlanConnection >*/
+	NM_DEVICE_VLAN_ERROR_ID_MISMATCH,             /*< nick=IdMismatch >*/
+	NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH,      /*< nick=InterfaceMismatch >*/
+} NMDeviceVlanError;
+
+#define NM_DEVICE_VLAN_ERROR nm_device_vlan_error_quark ()
+GQuark nm_device_vlan_error_quark (void);
+
 #define NM_DEVICE_VLAN_HW_ADDRESS  "hw-address"
 #define NM_DEVICE_VLAN_CARRIER     "carrier"
 #define NM_DEVICE_VLAN_VLAN_ID     "vlan-id"
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
index ab92613..5c70cbd 100644
--- a/libnm-glib/nm-device-wifi.c
+++ b/libnm-glib/nm-device-wifi.c
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2011 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #include <config.h>
@@ -86,6 +86,23 @@ enum {
 static guint signals[LAST_SIGNAL] = { 0 };
 
 /**
+ * nm_device_wifi_error_quark:
+ *
+ * Registers an error quark for #NMDeviceWifi if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceWifi errors.
+ **/
+GQuark
+nm_device_wifi_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-wifi-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_wifi_new:
  * @connection: the #DBusGConnection
  * @path: the DBus object path of the device
@@ -390,7 +407,7 @@ has_proto (NMSettingWirelessSecurity *s_wsec, const char *proto)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
@@ -402,24 +419,40 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	NMDeviceWifiCapabilities wifi_caps;
 	const char *key_mgmt;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_WIRELESS_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_WIRELESS_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_NOT_WIFI_CONNECTION,
+		             "The connection was not a Wi-Fi connection.");
 		return FALSE;
+	}
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
-	if (!s_wifi)
+	if (!s_wifi) {
+		g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_INVALID_WIFI_CONNECTION,
+		             "The connection was not a valid Wi-Fi connection.");
 		return FALSE;
+	}
 
 	/* Check MAC address */
 	hw_str = nm_device_wifi_get_permanent_hw_address (NM_DEVICE_WIFI (device));
 	if (hw_str) {
 		hw_mac = ether_aton (hw_str);
+		if (!hw_mac) {
+			g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_INVALID_DEVICE_MAC,
+			             "Invalid device MAC address.");
+			return FALSE;
+		}
 		mac = nm_setting_wireless_get_mac_address (s_wifi);
-		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) {
+			g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_MAC_MISMATCH,
+			             "The MACs of the device and the connection didn't match.");
 			return FALSE;
+		}
 	}
 
 	/* Check device capabilities; we assume all devices can do WEP at least */
@@ -434,12 +467,18 @@ connection_valid (NMDevice *device, NMConnection *connection)
 		    || !g_strcmp0 (key_mgmt, "wpa-eap")) {
 
 			/* Is device only WEP capable? */
-			if (!(wifi_caps & WPA_CAPS))
+			if (!(wifi_caps & WPA_CAPS)) {
+				g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_WPA_CAPS,
+				             "The device missed WPA capabilities required by the connection.");
 				return FALSE;
+			}
 
 			/* Make sure WPA2/RSN-only connections don't get chosen for WPA-only cards */
-			if (has_proto (s_wsec, "rsn") && !has_proto (s_wsec, "wpa") && !(wifi_caps & RSN_CAPS))
+			if (has_proto (s_wsec, "rsn") && !has_proto (s_wsec, "wpa") && !(wifi_caps & RSN_CAPS)) {
+				g_set_error (error, NM_DEVICE_WIFI_ERROR, NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_RSN_CAPS,
+				             "The device missed WPA2/RSN capabilities required by the connection.");
 				return FALSE;
+			}
 		}
 	}
 
diff --git a/libnm-glib/nm-device-wifi.h b/libnm-glib/nm-device-wifi.h
index fb2ab27..13f1cb8 100644
--- a/libnm-glib/nm-device-wifi.h
+++ b/libnm-glib/nm-device-wifi.h
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #ifndef NM_DEVICE_WIFI_H
@@ -36,6 +36,31 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_WIFI))
 #define NM_DEVICE_WIFI_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass))
 
+/**
+ * NMDeviceWifiError:
+ * @NM_DEVICE_WIFI_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_WIFI_ERROR_NOT_WIFI_CONNECTION: the connection was not of Wi-Fi type
+ * @NM_DEVICE_WIFI_ERROR_INVALID_WIFI_CONNECTION: the Wi-Fi connection was invalid
+ * @NM_DEVICE_WIFI_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_WIFI_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ * @NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_WPA_CAPS: the device missed WPA capabilities
+ * required by the connection
+ * @NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_RSN_CAPS: the device missed RSN capabilities
+ * required by the connection
+ */
+typedef enum {
+	NM_DEVICE_WIFI_ERROR_UNKNOWN = 0,             /*< nick=UnknownError >*/
+	NM_DEVICE_WIFI_ERROR_NOT_WIFI_CONNECTION,     /*< nick=NotWifiConnection >*/
+	NM_DEVICE_WIFI_ERROR_INVALID_WIFI_CONNECTION, /*< nick=InvalidWifiConnection >*/
+	NM_DEVICE_WIFI_ERROR_INVALID_DEVICE_MAC,      /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_WIFI_ERROR_MAC_MISMATCH,            /*< nick=MacMismatch >*/
+	NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_WPA_CAPS, /*< nick=MissingDeviceWpaCaps >*/
+	NM_DEVICE_WIFI_ERROR_MISSING_DEVICE_RSN_CAPS, /*< nick=MissingDeviceRsnCaps >*/
+} NMDeviceWifiError;
+
+#define NM_DEVICE_WIFI_ERROR nm_device_wifi_error_quark ()
+GQuark nm_device_wifi_error_quark (void);
+
 #define NM_DEVICE_WIFI_HW_ADDRESS          "hw-address"
 #define NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS "perm-hw-address"
 #define NM_DEVICE_WIFI_MODE                "mode"
diff --git a/libnm-glib/nm-device-wimax.c b/libnm-glib/nm-device-wimax.c
index 427a404..691617b 100644
--- a/libnm-glib/nm-device-wimax.c
+++ b/libnm-glib/nm-device-wimax.c
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  * Copyright (C) 2009 Novell, Inc.
  */
 
@@ -87,6 +87,23 @@ enum {
 static guint signals[LAST_SIGNAL] = { 0 };
 
 /**
+ * nm_device_wimax_error_quark:
+ *
+ * Registers an error quark for #NMDeviceWimax if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceWimax errors.
+ **/
+GQuark
+nm_device_wimax_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-wimax-error-quark");
+	return quark;
+}
+
+/**
  * nm_device_wimax_new:
  * @connection: the #DBusGConnection
  * @path: the D-Bus object path of the WiMAX device
@@ -363,7 +380,7 @@ nm_device_wimax_get_bsid (NMDeviceWimax *self)
 }
 
 static gboolean
-connection_valid (NMDevice *device, NMConnection *connection)
+connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMSettingConnection *s_con;
 	NMSettingWimax *s_wimax;
@@ -372,24 +389,40 @@ connection_valid (NMDevice *device, NMConnection *connection)
 	const char *hw_str;
 	struct ether_addr *hw_mac;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	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_WIMAX_SETTING_NAME) != 0)
+	if (strcmp (ctype, NM_SETTING_WIMAX_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION,
+		             "The connection was not a Wimax connection.");
 		return FALSE;
+	}
 
 	s_wimax = nm_connection_get_setting_wimax (connection);
-	if (!s_wimax)
+	if (!s_wimax) {
+		g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION,
+		             "The connection was not a valid Wimax connection.");
 		return FALSE;
+	}
 
 	/* Check MAC address */
 	hw_str = nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device));
 	if (hw_str) {
 		hw_mac = ether_aton (hw_str);
+		if (!hw_mac) {
+			g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC,
+			             "Invalid device MAC address.");
+			return FALSE;
+		}
 		mac = nm_setting_wimax_get_mac_address (s_wimax);
-		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN))
+		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) {
+			g_set_error (error, NM_DEVICE_WIMAX_ERROR, NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH,
+			             "The MACs of the device and the connection didn't match.");
 			return FALSE;
+		}
 	}
 
 	return TRUE;
diff --git a/libnm-glib/nm-device-wimax.h b/libnm-glib/nm-device-wimax.h
index 5e19bba..e391d4d 100644
--- a/libnm-glib/nm-device-wimax.h
+++ b/libnm-glib/nm-device-wimax.h
@@ -17,7 +17,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 - 2012 Red Hat, Inc.
  * Copyright (C) 2009 Novell, Inc.
  */
 
@@ -36,6 +36,25 @@ G_BEGIN_DECLS
 #define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_WIMAX))
 #define NM_DEVICE_WIMAX_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass))
 
+/**
+ * NMDeviceWimaxError:
+ * @NM_DEVICE_WIMAX_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION: the connection was not of WiMax type
+ * @NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION: the WiMax connection was invalid
+ * @NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC: the device's MAC was invalid
+ * @NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH: the MACs of the connection and the device mismatched
+ */
+typedef enum {
+	NM_DEVICE_WIMAX_ERROR_UNKNOWN = 0,              /*< nick=UnknownError >*/
+	NM_DEVICE_WIMAX_ERROR_NOT_WIMAX_CONNECTION,     /*< nick=NotWimaxConnection >*/
+	NM_DEVICE_WIMAX_ERROR_INVALID_WIMAX_CONNECTION, /*< nick=InvalidWimaxConnection >*/
+	NM_DEVICE_WIMAX_ERROR_INVALID_DEVICE_MAC,       /*< nick=InvalidDeviceMac >*/
+	NM_DEVICE_WIMAX_ERROR_MAC_MISMATCH,             /*< nick=MacMismatch >*/
+} NMDeviceWimaxError;
+
+#define NM_DEVICE_WIMAX_ERROR nm_device_wimax_error_quark ()
+GQuark nm_device_wimax_error_quark (void);
+
 #define NM_DEVICE_WIMAX_HW_ADDRESS       "hw-address"
 #define NM_DEVICE_WIMAX_ACTIVE_NSP       "active-nsp"
 #define NM_DEVICE_WIMAX_CENTER_FREQUENCY "center-frequency"
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
index 3f582ee..4772357 100644
--- a/libnm-glib/nm-device.c
+++ b/libnm-glib/nm-device.c
@@ -1332,6 +1332,7 @@ nm_device_disconnect (NMDevice *device,
  * nm_device_connection_valid:
  * @device: an #NMDevice to validate @connection against
  * @connection: an #NMConnection to validate against @device
+ * @error: return location for a #GError, or %NULL
  *
  * Validates a given connection for a given #NMDevice object and returns
  * whether the connection may be activated with the device. For example if
@@ -1345,10 +1346,10 @@ nm_device_disconnect (NMDevice *device,
  * if is incompatible with the device's capabilities and characteristics.
  **/
 gboolean
-nm_device_connection_valid (NMDevice *device, NMConnection *connection)
+nm_device_connection_valid (NMDevice *device, NMConnection *connection, GError **error)
 {
 	if (NM_DEVICE_GET_CLASS (device)->connection_valid)
-		return NM_DEVICE_GET_CLASS (device)->connection_valid (device, connection);
+		return NM_DEVICE_GET_CLASS (device)->connection_valid (device, connection, error);
 	return FALSE;
 }
 
@@ -1382,7 +1383,7 @@ nm_device_filter_connections (NMDevice *device, const GSList *connections)
 		NMConnection *candidate = NM_CONNECTION (iter->data);
 
 		/* Connection applies to this device */
-		if (nm_device_connection_valid (device, candidate))
+		if (nm_device_connection_valid (device, candidate, NULL))
 			filtered = g_slist_prepend (filtered, candidate);
 	}
 
diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h
index 75c5197..37fd64d 100644
--- a/libnm-glib/nm-device.h
+++ b/libnm-glib/nm-device.h
@@ -77,7 +77,8 @@ typedef struct {
 	                       NMDeviceStateReason reason);
 
 	gboolean (*connection_valid)   (NMDevice *device,
-	                                NMConnection *connection);
+	                                NMConnection *connection,
+	                                GError **error);
 
 	/* Padding for future expansion */
 	void (*_reserved1) (void);
@@ -120,7 +121,8 @@ GSList *             nm_device_filter_connections   (NMDevice *device,
                                                      const GSList *connections);
 
 gboolean             nm_device_connection_valid     (NMDevice *device,
-                                                     NMConnection *connection);
+                                                     NMConnection *connection,
+                                                     GError **error);
 
 G_END_DECLS
 
-- 
1.7.7.6



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