summary refs log tree commit diff
path: root/libnm-core/nm-setting-bluetooth.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-setting-bluetooth.c')
-rw-r--r--libnm-core/nm-setting-bluetooth.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c
index 837b06c0..5b6ef3eb 100644
--- a/libnm-core/nm-setting-bluetooth.c
+++ b/libnm-core/nm-setting-bluetooth.c
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <net/ethernet.h>
 
+#include "nm-connection-private.h"
 #include "nm-setting-bluetooth.h"
 #include "nm-setting-cdma.h"
 #include "nm-setting-gsm.h"
@@ -43,7 +44,7 @@
  **/
 
 G_DEFINE_TYPE_WITH_CODE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING,
-                         _nm_register_setting (BLUETOOTH, 1))
+                         _nm_register_setting (BLUETOOTH, NM_SETTING_PRIORITY_HW_NON_BASE))
 NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BLUETOOTH)
 
 #define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate))
@@ -80,8 +81,8 @@ NMSetting *nm_setting_bluetooth_new (void)
  * Returns the connection method for communicating with the remote device (i.e.
  * either DUN to a DUN-capable device or PANU to a NAP-capable device).
  *
- * Returns: the type, either %NM_SETTING_BLUETOOTH_TYPE_PANU or
- * %NM_SETTING_BLUETOOTH_TYPE_DUN
+ * Returns: the type, either %NM_SETTING_BLUETOOTH_TYPE_PANU,
+ * %NM_SETTING_BLUETOOTH_TYPE_NAP or %NM_SETTING_BLUETOOTH_TYPE_DUN
  **/
 const char *
 nm_setting_bluetooth_get_connection_type (NMSettingBluetooth *setting)
@@ -112,17 +113,10 @@ static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
 	NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (setting);
+	const char *type;
+	gboolean missing_nap_bridge = FALSE;
 
-	if (!priv->bdaddr) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_MISSING_PROPERTY,
-		                     _("property is missing"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR);
-		return FALSE;
-	}
-
-	if (!nm_utils_hwaddr_valid (priv->bdaddr, ETH_ALEN)) {
+	if (priv->bdaddr && !nm_utils_hwaddr_valid (priv->bdaddr, ETH_ALEN)) {
 		g_set_error_literal (error,
 		                     NM_CONNECTION_ERROR,
 		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -131,27 +125,38 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (!priv->type) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_MISSING_PROPERTY,
-		                     _("property is missing"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
-		return FALSE;
-	} else if (!g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN) &&
-	           !g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_PANU)) {
+	type = priv->type;
+	if (!type) {
+		if (connection) {
+			/* We may infer the type from the (non-)existence of gsm/cdma/bridge settings. */
+			type = _nm_connection_detect_bluetooth_type (connection);
+		}
+		if (!type) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
+			return FALSE;
+		}
+	}
+
+	if (!NM_IN_STRSET (type, NM_SETTING_BLUETOOTH_TYPE_DUN,
+	                         NM_SETTING_BLUETOOTH_TYPE_NAP,
+	                         NM_SETTING_BLUETOOTH_TYPE_PANU)) {
+		nm_assert (priv->type == type);
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
 		             _("'%s' is not a valid value for the property"),
-		             priv->type);
+		             type);
 		g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
 		return FALSE;
 	}
 
 	/* Make sure the corresponding 'type' setting is present */
 	if (   connection
-	    && !strcmp (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN)) {
+	    && nm_streq (type, NM_SETTING_BLUETOOTH_TYPE_DUN)) {
 		gboolean gsm = FALSE, cdma = FALSE;
 
 		gsm = !!nm_connection_get_setting_gsm (connection);
@@ -176,6 +181,48 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	 * is required at the interface level.
 	 */
 
+	/* NAP mode needs a bridge setting, and a bridge needs a name. */
+	if (nm_streq (type, NM_SETTING_BLUETOOTH_TYPE_NAP)) {
+		if (!_nm_connection_verify_required_interface_name (connection, error))
+			return FALSE;
+		if (   connection
+		    && !nm_connection_get_setting_bridge (connection))
+			missing_nap_bridge = TRUE;
+	} else {
+		if (!priv->bdaddr) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR);
+			return FALSE;
+		}
+	}
+
+	/* errors form here are normalizable. */
+
+	if (!priv->type) {
+		/* as determined above, we can detect the bluetooth type. */
+		nm_assert (!missing_nap_bridge);
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
+		return NM_SETTING_VERIFY_NORMALIZABLE;
+	}
+
+	if (missing_nap_bridge) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_SETTING,
+		             _("'%s' connection requires '%s' setting"),
+		             NM_SETTING_BLUETOOTH_TYPE_NAP,
+		             NM_SETTING_BRIDGE_SETTING_NAME);
+		g_prefix_error (error, "%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME);
+		return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+	}
+
 	return TRUE;
 }