summary refs log tree commit diff
path: root/libnm-core/nm-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-connection.c')
-rw-r--r--libnm-core/nm-connection.c623
1 files changed, 388 insertions, 235 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index c1b75068..d5e28f7b 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -93,10 +93,16 @@ _setting_release (gpointer key, gpointer value, gpointer user_data)
 static void
 _nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
 {
-	NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
-	const char *name = G_OBJECT_TYPE_NAME (setting);
+	NMConnectionPrivate *priv;
+	const char *name;
 	NMSetting *s_old;
 
+	nm_assert (NM_IS_CONNECTION (connection));
+	nm_assert (NM_IS_SETTING (setting));
+
+	priv = NM_CONNECTION_GET_PRIVATE (connection);
+	name = G_OBJECT_TYPE_NAME (setting);
+
 	if ((s_old = g_hash_table_lookup (priv->settings, (gpointer) name)))
 		g_signal_handlers_disconnect_by_func (s_old, setting_changed_cb, connection);
 	g_hash_table_insert (priv->settings, (gpointer) name, setting);
@@ -160,6 +166,24 @@ nm_connection_remove_setting (NMConnection *connection, GType setting_type)
 	_nm_connection_remove_setting (connection, setting_type);
 }
 
+static gpointer
+_connection_get_setting (NMConnection *connection, GType setting_type)
+{
+	nm_assert (NM_IS_CONNECTION (connection));
+	nm_assert (g_type_is_a (setting_type, NM_TYPE_SETTING));
+
+	return g_hash_table_lookup (NM_CONNECTION_GET_PRIVATE (connection)->settings,
+	                            g_type_name (setting_type));
+}
+
+static gpointer
+_connection_get_setting_check (NMConnection *connection, GType setting_type)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return _connection_get_setting (connection, setting_type);
+}
+
 /**
  * nm_connection_get_setting:
  * @connection: a #NMConnection
@@ -174,11 +198,9 @@ nm_connection_remove_setting (NMConnection *connection, GType setting_type)
 NMSetting *
 nm_connection_get_setting (NMConnection *connection, GType setting_type)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 	g_return_val_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING), NULL);
 
-	return (NMSetting *) g_hash_table_lookup (NM_CONNECTION_GET_PRIVATE (connection)->settings,
-	                                          g_type_name (setting_type));
+	return _connection_get_setting_check (connection, setting_type);
 }
 
 /**
@@ -198,11 +220,9 @@ nm_connection_get_setting_by_name (NMConnection *connection, const char *name)
 	GType type;
 
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-	g_return_val_if_fail (name != NULL, NULL);
 
 	type = nm_setting_lookup_type (name);
-
-	return type ? nm_connection_get_setting (connection, type) : NULL;
+	return type ? _connection_get_setting (connection, type) : NULL;
 }
 
 static gboolean
@@ -496,7 +516,7 @@ nm_connection_compare (NMConnection *a,
 }
 
 
-static void
+static gboolean
 diff_one_connection (NMConnection *a,
                      NMConnection *b,
                      NMSettingCompareFlags flags,
@@ -506,6 +526,7 @@ diff_one_connection (NMConnection *a,
 	NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (a);
 	GHashTableIter iter;
 	NMSetting *a_setting = NULL;
+	gboolean diff_found = FALSE;
 
 	g_hash_table_iter_init (&iter, priv->settings);
 	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &a_setting)) {
@@ -521,11 +542,14 @@ diff_one_connection (NMConnection *a,
 		if (results)
 			new_results = FALSE;
 
-		if (!nm_setting_diff (a_setting, b_setting, flags, invert_results, &results)) {
-			if (new_results)
-				g_hash_table_insert (diffs, g_strdup (setting_name), results);
-		}
+		if (!nm_setting_diff (a_setting, b_setting, flags, invert_results, &results))
+			diff_found = TRUE;
+
+		if (new_results && results)
+			g_hash_table_insert (diffs, g_strdup (setting_name), results);
 	}
+
+	return diff_found;
 }
 
 /**
@@ -554,12 +578,11 @@ nm_connection_diff (NMConnection *a,
                     GHashTable **out_settings)
 {
 	GHashTable *diffs;
+	gboolean diff_found = FALSE;
 
 	g_return_val_if_fail (NM_IS_CONNECTION (a), FALSE);
-	g_return_val_if_fail (out_settings != NULL, FALSE);
-	g_return_val_if_fail (*out_settings == NULL, FALSE);
-	if (b)
-		g_return_val_if_fail (NM_IS_CONNECTION (b), FALSE);
+	g_return_val_if_fail (!out_settings || !*out_settings, FALSE);
+	g_return_val_if_fail (!b || NM_IS_CONNECTION (b), FALSE);
 
 	if (a == b)
 		return TRUE;
@@ -567,16 +590,22 @@ nm_connection_diff (NMConnection *a,
 	diffs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
 
 	/* Diff A to B, then B to A to capture keys in B that aren't in A */
-	diff_one_connection (a, b, flags, FALSE, diffs);
-	if (b)
-		diff_one_connection (b, a, flags, TRUE, diffs);
+	if (diff_one_connection (a, b, flags, FALSE, diffs))
+		diff_found = TRUE;
+	if (   b
+	    && diff_one_connection (b, a, flags, TRUE, diffs))
+		diff_found = TRUE;
 
-	if (g_hash_table_size (diffs) == 0)
+	nm_assert (diff_found == (g_hash_table_size (diffs) != 0));
+
+	if (g_hash_table_size (diffs) == 0) {
 		g_hash_table_destroy (diffs);
-	else
-		*out_settings = diffs;
+		diffs = NULL;
+	}
+
+	NM_SET_OUT (out_settings, diffs);
 
-	return *out_settings ? FALSE : TRUE;
+	return !diff_found;
 }
 
 NMSetting *
@@ -585,19 +614,31 @@ _nm_connection_find_base_type_setting (NMConnection *connection)
 	NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
 	GHashTableIter iter;
 	NMSetting *setting = NULL, *s_iter;
+	NMSettingPriority setting_prio, s_iter_prio;
 
 	g_hash_table_iter_init (&iter, priv->settings);
 	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &s_iter)) {
-		if (!_nm_setting_is_base_type (s_iter))
+		s_iter_prio = _nm_setting_get_base_type_priority (s_iter);
+		if (s_iter_prio == NM_SETTING_PRIORITY_INVALID)
 			continue;
 
 		if (setting) {
-			/* FIXME: currently, if there is more than one matching base type,
-			 * we cannot detect the base setting.
-			 * See: https://bugzilla.gnome.org/show_bug.cgi?id=696936#c8 */
-			return NULL;
+			if (s_iter_prio > setting_prio) {
+				continue;
+			} else if (s_iter_prio == setting_prio) {
+				NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
+				const char *type;
+
+				if (s_con) {
+					type = nm_setting_connection_get_connection_type (s_con);
+					if (type)
+						return nm_connection_get_setting_by_name (connection, type);
+				}
+				return NULL;
+			}
 		}
 		setting = s_iter;
+		setting_prio = s_iter_prio;
 	}
 	return setting;
 }
@@ -652,6 +693,26 @@ _normalize_connection_type (NMConnection *self)
 }
 
 const char *
+_nm_connection_detect_bluetooth_type (NMConnection *self)
+{
+	NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (self);
+
+	if (   s_bt
+	    && nm_setting_bluetooth_get_connection_type (s_bt)) {
+		if (   nm_connection_get_setting_gsm (self)
+		    || nm_connection_get_setting_cdma (self))
+			return NM_SETTING_BLUETOOTH_TYPE_DUN;
+		if (nm_connection_get_setting_bridge (self))
+			return NM_SETTING_BLUETOOTH_TYPE_NAP;
+		return NM_SETTING_BLUETOOTH_TYPE_PANU;
+	}
+
+	/* NULL means the connection is not a bluetooth type, or it needs
+	 * no normalization, as the type is set explicitly. */
+	return NULL;
+}
+
+const char *
 _nm_connection_detect_slave_type (NMConnection *connection, NMSetting **out_s_port)
 {
 	NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
@@ -668,6 +729,10 @@ _nm_connection_detect_slave_type (NMConnection *connection, NMSetting **out_s_po
 			i_slave_type = NM_SETTING_BRIDGE_SETTING_NAME;
 		else if (!strcmp (name, NM_SETTING_TEAM_PORT_SETTING_NAME))
 			i_slave_type = NM_SETTING_TEAM_SETTING_NAME;
+		else if (!strcmp (name, NM_SETTING_OVS_PORT_SETTING_NAME))
+			i_slave_type = NM_SETTING_OVS_BRIDGE_SETTING_NAME;
+		else if (!strcmp (name, NM_SETTING_OVS_INTERFACE_SETTING_NAME))
+			i_slave_type = NM_SETTING_OVS_PORT_SETTING_NAME;
 		else
 			continue;
 
@@ -748,9 +813,20 @@ _normalize_ethernet_link_neg (NMConnection *self)
 }
 
 static gboolean
+_without_ip_config (NMConnection *self)
+{
+	const char *connection_type = nm_connection_get_connection_type (self);
+
+	g_return_val_if_fail (connection_type, FALSE);
+	if (strcmp (connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0)
+		return FALSE;
+
+	return !!nm_setting_connection_get_master (nm_connection_get_setting_connection (self));
+}
+
+static gboolean
 _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 {
-	NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
 	const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
 	const char *default_ip6_method = NULL;
 	NMSettingIPConfig *s_ip4, *s_ip6;
@@ -768,7 +844,7 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 	s_ip6 = nm_connection_get_setting_ip6_config (self);
 	s_proxy = nm_connection_get_setting_proxy (self);
 
-	if (nm_setting_connection_get_master (s_con)) {
+	if (_without_ip_config (self)) {
 		/* Slave connections don't have IP configuration. */
 
 		if (s_ip4)
@@ -1021,15 +1097,62 @@ _normalize_team_port_config (NMConnection *self, GHashTable *parameters)
 }
 
 static gboolean
+_normalize_bluetooth_type (NMConnection *self, GHashTable *parameters)
+{
+	const char *type = _nm_connection_detect_bluetooth_type (self);
+
+	if (type) {
+		g_object_set (nm_connection_get_setting_bluetooth (self),
+		              NM_SETTING_BLUETOOTH_TYPE, type,
+		              NULL);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+_normalize_ovs_interface_type (NMConnection *self, GHashTable *parameters)
+{
+	NMSettingOvsInterface *s_ovs_interface = nm_connection_get_setting_ovs_interface (self);
+	gboolean modified;
+	int v;
+
+	if (!s_ovs_interface)
+		return FALSE;
+
+	v = _nm_setting_ovs_interface_verify_interface_type (s_ovs_interface,
+	                                                     self,
+	                                                     TRUE,
+	                                                     &modified,
+	                                                     NULL);
+	if (v != TRUE)
+		g_return_val_if_reached (modified);
+
+	return modified;
+}
+
+static gboolean
 _normalize_required_settings (NMConnection *self, GHashTable *parameters)
 {
+	NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (self);
+	NMSetting *s_bridge;
+	gboolean changed = FALSE;
+
 	if (nm_connection_get_setting_vlan (self)) {
 		if (!nm_connection_get_setting_wired (self)) {
 			nm_connection_add_setting (self, nm_setting_wired_new ());
-			return TRUE;
+			changed = TRUE;
 		}
 	}
-	return FALSE;
+	if (s_bt && nm_streq0 (nm_setting_bluetooth_get_connection_type (s_bt), NM_SETTING_BLUETOOTH_TYPE_NAP)) {
+		if (!nm_connection_get_setting_bridge (self)) {
+			s_bridge = nm_setting_bridge_new ();
+			g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL);
+			nm_connection_add_setting (self, s_bridge);
+			changed = TRUE;
+		}
+	}
+	return changed;
 }
 
 static gboolean
@@ -1165,40 +1288,42 @@ _nm_connection_verify (NMConnection *connection, GError **error)
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
 	s_proxy = nm_connection_get_setting_proxy (connection);
 
-	if (nm_setting_connection_get_master (s_con)) {
-		if (   NM_IN_SET (normalizable_error_type, NM_SETTING_VERIFY_SUCCESS,
-		                                           NM_SETTING_VERIFY_NORMALIZABLE)
-		    && (s_ip4 || s_ip6 || s_proxy)) {
-			g_clear_error (&normalizable_error);
-			g_set_error_literal (&normalizable_error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_SETTING,
-			                     _("setting not allowed in slave connection"));
-			g_prefix_error (&normalizable_error, "%s: ",
-			                s_ip4
-			                ? NM_SETTING_IP4_CONFIG_SETTING_NAME
-			                : (s_ip6
-			                   ? NM_SETTING_IP6_CONFIG_SETTING_NAME
-			                   : NM_SETTING_PROXY_SETTING_NAME));
-			/* having a slave with IP config *was* and is a verify() error. */
-			normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
-		}
-	} else {
-		if (   NM_IN_SET (normalizable_error_type, NM_SETTING_VERIFY_SUCCESS)
-		    && (!s_ip4 || !s_ip6 || !s_proxy)) {
-			g_set_error_literal (&normalizable_error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_MISSING_SETTING,
-			                     _("setting is required for non-slave connections"));
-			g_prefix_error (&normalizable_error, "%s: ",
-			                !s_ip4
-			                ? NM_SETTING_IP4_CONFIG_SETTING_NAME
-			                : (!s_ip6
-			                   ? NM_SETTING_IP6_CONFIG_SETTING_NAME
-			                   : NM_SETTING_PROXY_SETTING_NAME));
-			/* having a master without IP config was not a verify() error, accept
-			 * it for backward compatibility. */
-			normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE;
+	nm_assert (normalizable_error_type != NM_SETTING_VERIFY_ERROR);
+	if (NM_IN_SET (normalizable_error_type, NM_SETTING_VERIFY_SUCCESS,
+	                                        NM_SETTING_VERIFY_NORMALIZABLE)) {
+		if (_without_ip_config (connection)) {
+			if (s_ip4 || s_ip6 || s_proxy) {
+				g_clear_error (&normalizable_error);
+				g_set_error_literal (&normalizable_error,
+				                     NM_CONNECTION_ERROR,
+				                     NM_CONNECTION_ERROR_INVALID_SETTING,
+				                     _("setting not allowed in slave connection"));
+				g_prefix_error (&normalizable_error, "%s: ",
+				                s_ip4
+				                ? NM_SETTING_IP4_CONFIG_SETTING_NAME
+				                : (s_ip6
+				                   ? NM_SETTING_IP6_CONFIG_SETTING_NAME
+				                   : NM_SETTING_PROXY_SETTING_NAME));
+				/* having a slave with IP config *was* and is a verify() error. */
+				normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+			}
+		} else {
+			if (   normalizable_error_type == NM_SETTING_VERIFY_SUCCESS
+			    && (!s_ip4 || !s_ip6 || !s_proxy)) {
+				g_set_error_literal (&normalizable_error,
+				                     NM_CONNECTION_ERROR,
+				                     NM_CONNECTION_ERROR_MISSING_SETTING,
+				                     _("setting is required for non-slave connections"));
+				g_prefix_error (&normalizable_error, "%s: ",
+				                !s_ip4
+				                ? NM_SETTING_IP4_CONFIG_SETTING_NAME
+				                : (!s_ip6
+				                   ? NM_SETTING_IP6_CONFIG_SETTING_NAME
+				                   : NM_SETTING_PROXY_SETTING_NAME));
+				/* having a master without IP config was not a verify() error, accept
+				 * it for backward compatibility. */
+				normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE;
+			}
 		}
 	}
 
@@ -1309,6 +1434,8 @@ nm_connection_normalize (NMConnection *connection,
 	was_modified |= _normalize_wireless_mac_address_randomization (connection, parameters);
 	was_modified |= _normalize_team_config (connection, parameters);
 	was_modified |= _normalize_team_port_config (connection, parameters);
+	was_modified |= _normalize_bluetooth_type (connection, parameters);
+	was_modified |= _normalize_ovs_interface_type (connection, parameters);
 
 	/* Verify anew. */
 	success = _nm_connection_verify (connection, error);
@@ -1326,6 +1453,7 @@ nm_connection_normalize (NMConnection *connection,
 			                     NM_CONNECTION_ERROR_FAILED,
 			                     _("Unexpected failure to normalize the connection"));
 		}
+		g_warning ("connection did not verify after normalization: %s", error ? (*error)->message : "??");
 		g_return_val_if_reached (FALSE);
 	}
 
@@ -1640,19 +1768,9 @@ nm_connection_to_dbus (NMConnection *connection,
 gboolean
 nm_connection_is_type (NMConnection *connection, const char *type)
 {
-	NMSettingConnection *s_con;
-	const char *type2;
-
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
-	g_return_val_if_fail (type != NULL, FALSE);
+	g_return_val_if_fail (type, FALSE);
 
-	s_con = nm_connection_get_setting_connection (connection);
-	if (!s_con)
-		return FALSE;
-
-	type2 = nm_setting_connection_get_connection_type (s_con);
-
-	return (g_strcmp0 (type2, type) == 0);
+	return nm_streq0 (type, nm_connection_get_connection_type (connection));
 }
 
 static int
@@ -1669,52 +1787,82 @@ _for_each_sort (NMSetting **p_a, NMSetting **p_b, void *unused)
 }
 
 /**
- * nm_connection_for_each_setting_value:
- * @connection: the #NMConnection
- * @func: (scope call): user-supplied function called for each setting's property
- * @user_data: user data passed to @func at each invocation
+ * nm_connection_get_settings:
+ * @connection: the #NMConnection instance
+ * @out_length: (allow-none): (out): the length of the returned array
  *
- * Iterates over the properties of each #NMSetting object in the #NMConnection,
- * calling the supplied user function for each property.
- **/
-void
-nm_connection_for_each_setting_value (NMConnection *connection,
-                                      NMSettingValueIterFn func,
-                                      gpointer user_data)
+ * Retrieves the settings in @connection.
+ *
+ * The returned array is %NULL-terminated.
+ *
+ * Returns: (array length=out_length) (transfer container): a
+ *   %NULL-terminated array containing every setting of
+ *   @connection.
+ *   If the connection has no settings, %NULL is returned.
+ *
+ * Since: 1.10
+ */
+NMSetting **
+nm_connection_get_settings (NMConnection *connection,
+                            guint *out_length)
 {
 	NMConnectionPrivate *priv;
-	gs_free NMSetting **arr_free = NULL;
-	NMSetting *arr_temp[20], **arr;
+	NMSetting **arr;
 	GHashTableIter iter;
-	gpointer value;
+	NMSetting *setting;
 	guint i, size;
 
-	g_return_if_fail (NM_IS_CONNECTION (connection));
-	g_return_if_fail (func != NULL);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	priv = NM_CONNECTION_GET_PRIVATE (connection);
 
 	size = g_hash_table_size (priv->settings);
-	if (!size)
-		return;
 
-	if (size > G_N_ELEMENTS (arr_temp))
-		arr = arr_free = g_new (NMSetting *, size);
-	else
-		arr = arr_temp;
+	if (!size) {
+		NM_SET_OUT (out_length, 0);
+		return NULL;
+	}
+
+	arr = g_new (NMSetting *, size + 1);
 
 	g_hash_table_iter_init (&iter, priv->settings);
-	for (i = 0; g_hash_table_iter_next (&iter, NULL, &value); i++)
-		arr[i] = NM_SETTING (value);
-	g_assert (i == size);
+	for (i = 0; g_hash_table_iter_next (&iter, NULL, (gpointer *) &setting); i++)
+		arr[i] = setting;
+	nm_assert (i == size);
+	arr[size] = NULL;
 
 	/* sort the settings. This has an effect on the order in which keyfile
 	 * prints them. */
 	if (size > 1)
 		g_qsort_with_data (arr, size, sizeof (NMSetting *), (GCompareDataFunc) _for_each_sort, NULL);
 
-	for (i = 0; i < size; i++)
-		nm_setting_enumerate_values (arr[i], func, user_data);
+	NM_SET_OUT (out_length, size);
+	return arr;
+}
+
+/**
+ * nm_connection_for_each_setting_value:
+ * @connection: the #NMConnection
+ * @func: (scope call): user-supplied function called for each setting's property
+ * @user_data: user data passed to @func at each invocation
+ *
+ * Iterates over the properties of each #NMSetting object in the #NMConnection,
+ * calling the supplied user function for each property.
+ **/
+void
+nm_connection_for_each_setting_value (NMConnection *connection,
+                                      NMSettingValueIterFn func,
+                                      gpointer user_data)
+{
+	gs_free NMSetting **settings = NULL;
+	guint i, length = 0;
+
+	g_return_if_fail (NM_IS_CONNECTION (connection));
+	g_return_if_fail (func);
+
+	settings = nm_connection_get_settings (connection, &length);
+	for (i = 0; i < length; i++)
+		nm_setting_enumerate_values (settings[i], func, user_data);
 }
 
 /**
@@ -1764,10 +1912,7 @@ nm_connection_set_path (NMConnection *connection, const char *path)
 	priv = NM_CONNECTION_GET_PRIVATE (connection);
 
 	g_free (priv->path);
-	priv->path = NULL;
-
-	if (path)
-		priv->path = g_strdup (path);
+	priv->path = g_strdup (path);
 }
 
 /**
@@ -1805,10 +1950,7 @@ nm_connection_get_interface_name (NMConnection *connection)
 {
 	NMSettingConnection *s_con;
 
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
 	s_con = nm_connection_get_setting_connection (connection);
-
 	return s_con ? nm_setting_connection_get_interface_name (s_con) : NULL;
 }
 
@@ -1818,6 +1960,9 @@ _nm_connection_verify_required_interface_name (NMConnection *connection,
 {
 	const char *interface_name;
 
+	if (!connection)
+		return TRUE;
+
 	interface_name = nm_connection_get_interface_name (connection);
 	if (interface_name)
 		return TRUE;
@@ -1843,13 +1988,8 @@ nm_connection_get_uuid (NMConnection *connection)
 {
 	NMSettingConnection *s_con;
 
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
 	s_con = nm_connection_get_setting_connection (connection);
-	if (!s_con)
-		return NULL;
-
-	return nm_setting_connection_get_uuid (s_con);
+	return s_con ? nm_setting_connection_get_uuid (s_con) : NULL;
 }
 
 /**
@@ -1865,13 +2005,8 @@ nm_connection_get_id (NMConnection *connection)
 {
 	NMSettingConnection *s_con;
 
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
 	s_con = nm_connection_get_setting_connection (connection);
-	if (!s_con)
-		return NULL;
-
-	return nm_setting_connection_get_id (s_con);
+	return s_con ? nm_setting_connection_get_id (s_con) : NULL;
 }
 
 /**
@@ -1887,13 +2022,8 @@ nm_connection_get_connection_type (NMConnection *connection)
 {
 	NMSettingConnection *s_con;
 
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
 	s_con = nm_connection_get_setting_connection (connection);
-	if (!s_con)
-		return NULL;
-
-	return nm_setting_connection_get_connection_type (s_con);
+	return s_con ? nm_setting_connection_get_connection_type (s_con) : NULL;
 }
 
 /**
@@ -1911,7 +2041,8 @@ nm_connection_is_virtual (NMConnection *connection)
 	const char *type;
 
 	type = nm_connection_get_connection_type (connection);
-	g_return_val_if_fail (type != NULL, FALSE);
+	if (!type)
+		return FALSE;
 
 	if (   !strcmp (type, NM_SETTING_BOND_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_DUMMY_SETTING_NAME)
@@ -1922,6 +2053,9 @@ nm_connection_is_virtual (NMConnection *connection)
 	    || !strcmp (type, NM_SETTING_IP_TUNNEL_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_MACSEC_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_MACVLAN_SETTING_NAME)
+	    || !strcmp (type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)
+	    || !strcmp (type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)
+	    || !strcmp (type, NM_SETTING_OVS_PORT_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_VXLAN_SETTING_NAME))
 		return TRUE;
 
@@ -1929,8 +2063,17 @@ nm_connection_is_virtual (NMConnection *connection)
 		NMSettingInfiniband *s_ib;
 
 		s_ib = nm_connection_get_setting_infiniband (connection);
-		g_return_val_if_fail (s_ib != NULL, FALSE);
-		return nm_setting_infiniband_get_virtual_interface_name (s_ib) != NULL;
+		return s_ib && nm_setting_infiniband_get_virtual_interface_name (s_ib);
+	}
+
+	if (nm_streq (type, NM_SETTING_BLUETOOTH_SETTING_NAME))
+		return !!_nm_connection_get_setting_bluetooth_for_nap (connection);
+
+	if (nm_streq (type, NM_SETTING_PPPOE_SETTING_NAME)) {
+		NMSettingPppoe *s_pppoe;
+
+		s_pppoe = nm_connection_get_setting_pppoe (connection);
+		return !!nm_setting_pppoe_get_parent (s_pppoe);
 	}
 
 	return FALSE;
@@ -1953,10 +2096,11 @@ nm_connection_get_virtual_device_description (NMConnection *connection)
 	const char *type;
 	const char *iface = NULL, *display_type = NULL;
 
-	iface = nm_connection_get_interface_name (connection);
-
 	type = nm_connection_get_connection_type (connection);
-	g_return_val_if_fail (type != NULL, FALSE);
+	if (!type)
+		return NULL;
+
+	iface = nm_connection_get_interface_name (connection);
 
 	if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME))
 		display_type = _("Bond");
@@ -1991,9 +2135,7 @@ nm_connection_get_virtual_device_description (NMConnection *connection)
 NMSetting8021x *
 nm_connection_get_setting_802_1x (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_802_1X);
 }
 
 /**
@@ -2007,9 +2149,7 @@ nm_connection_get_setting_802_1x (NMConnection *connection)
 NMSettingBluetooth *
 nm_connection_get_setting_bluetooth (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_BLUETOOTH);
 }
 
 /**
@@ -2023,9 +2163,7 @@ nm_connection_get_setting_bluetooth (NMConnection *connection)
 NMSettingBond *
 nm_connection_get_setting_bond (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingBond *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BOND);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_BOND);
 }
 
 /**
@@ -2039,9 +2177,7 @@ nm_connection_get_setting_bond (NMConnection *connection)
 NMSettingTeam *
 nm_connection_get_setting_team (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingTeam *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_TEAM);
 }
 
 /**
@@ -2055,9 +2191,7 @@ nm_connection_get_setting_team (NMConnection *connection)
 NMSettingTeamPort *
 nm_connection_get_setting_team_port (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingTeamPort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM_PORT);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_TEAM_PORT);
 }
 
 /**
@@ -2071,9 +2205,7 @@ nm_connection_get_setting_team_port (NMConnection *connection)
 NMSettingBridge *
 nm_connection_get_setting_bridge (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingBridge *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_BRIDGE);
 }
 
 /**
@@ -2087,9 +2219,7 @@ nm_connection_get_setting_bridge (NMConnection *connection)
 NMSettingCdma *
 nm_connection_get_setting_cdma (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_CDMA);
 }
 
 /**
@@ -2103,9 +2233,7 @@ nm_connection_get_setting_cdma (NMConnection *connection)
 NMSettingConnection *
 nm_connection_get_setting_connection (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_CONNECTION);
 }
 
 /**
@@ -2119,9 +2247,7 @@ nm_connection_get_setting_connection (NMConnection *connection)
 NMSettingDcb *
 nm_connection_get_setting_dcb (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingDcb *) nm_connection_get_setting (connection, NM_TYPE_SETTING_DCB);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_DCB);
 }
 
 /**
@@ -2137,9 +2263,7 @@ nm_connection_get_setting_dcb (NMConnection *connection)
 NMSettingDummy *
 nm_connection_get_setting_dummy (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingDummy *) nm_connection_get_setting (connection, NM_TYPE_SETTING_DUMMY);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_DUMMY);
 }
 
 /**
@@ -2153,9 +2277,7 @@ nm_connection_get_setting_dummy (NMConnection *connection)
 NMSettingGeneric *
 nm_connection_get_setting_generic (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingGeneric *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GENERIC);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_GENERIC);
 }
 
 /**
@@ -2169,9 +2291,7 @@ nm_connection_get_setting_generic (NMConnection *connection)
 NMSettingGsm *
 nm_connection_get_setting_gsm (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_GSM);
 }
 
 /**
@@ -2185,9 +2305,7 @@ nm_connection_get_setting_gsm (NMConnection *connection)
 NMSettingInfiniband *
 nm_connection_get_setting_infiniband (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_INFINIBAND);
 }
 
 /**
@@ -2206,9 +2324,7 @@ nm_connection_get_setting_infiniband (NMConnection *connection)
 NMSettingIPConfig *
 nm_connection_get_setting_ip4_config (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_IP4_CONFIG);
 }
 
 /**
@@ -2224,9 +2340,7 @@ nm_connection_get_setting_ip4_config (NMConnection *connection)
 NMSettingIPTunnel *
 nm_connection_get_setting_ip_tunnel (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingIPTunnel *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP_TUNNEL);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_IP_TUNNEL);
 }
 
 /**
@@ -2245,9 +2359,7 @@ nm_connection_get_setting_ip_tunnel (NMConnection *connection)
 NMSettingIPConfig *
 nm_connection_get_setting_ip6_config (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_IP6_CONFIG);
 }
 
 /**
@@ -2263,9 +2375,7 @@ nm_connection_get_setting_ip6_config (NMConnection *connection)
 NMSettingMacsec *
 nm_connection_get_setting_macsec (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingMacsec *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MACSEC);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_MACSEC);
 }
 
 /**
@@ -2281,9 +2391,7 @@ nm_connection_get_setting_macsec (NMConnection *connection)
 NMSettingMacvlan *
 nm_connection_get_setting_macvlan (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingMacvlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MACVLAN);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_MACVLAN);
 }
 
 /**
@@ -2297,9 +2405,71 @@ nm_connection_get_setting_macvlan (NMConnection *connection)
 NMSettingOlpcMesh *
 nm_connection_get_setting_olpc_mesh (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_OLPC_MESH);
+}
 
-	return (NMSettingOlpcMesh *) nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH);
+/**
+ * nm_connection_get_setting_ovs_bridge:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingOvsBridge the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingOvsBridge if the connection contains one, otherwise %NULL
+ *
+ * Since: 1.10
+ **/
+NMSettingOvsBridge *
+nm_connection_get_setting_ovs_bridge (NMConnection *connection)
+{
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_BRIDGE);
+}
+
+/**
+ * nm_connection_get_setting_ovs_interface:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingOvsInterface the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingOvsInterface if the connection contains one, otherwise %NULL
+ *
+ * Since: 1.10
+ **/
+NMSettingOvsInterface *
+nm_connection_get_setting_ovs_interface (NMConnection *connection)
+{
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_INTERFACE);
+}
+
+/**
+ * nm_connection_get_setting_ovs_patch:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingOvsPatch the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingOvsPatch if the connection contains one, otherwise %NULL
+ *
+ * Since: 1.10
+ **/
+NMSettingOvsPatch *
+nm_connection_get_setting_ovs_patch (NMConnection *connection)
+{
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_PATCH);
+}
+ 
+/**
+ * nm_connection_get_setting_ovs_port:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingOvsPort the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingOvsPort if the connection contains one, otherwise %NULL
+ *
+ * Since: 1.10
+ **/
+NMSettingOvsPort *
+nm_connection_get_setting_ovs_port (NMConnection *connection)
+{
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_PORT);
 }
 
 /**
@@ -2313,9 +2483,7 @@ nm_connection_get_setting_olpc_mesh (NMConnection *connection)
 NMSettingPpp *
 nm_connection_get_setting_ppp (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingPpp *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPP);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_PPP);
 }
 
 /**
@@ -2329,9 +2497,7 @@ nm_connection_get_setting_ppp (NMConnection *connection)
 NMSettingPppoe *
 nm_connection_get_setting_pppoe (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingPppoe *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_PPPOE);
 }
 
 /**
@@ -2347,9 +2513,7 @@ nm_connection_get_setting_pppoe (NMConnection *connection)
 NMSettingProxy *
 nm_connection_get_setting_proxy (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingProxy *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PROXY);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_PROXY);
 }
 
 /**
@@ -2363,9 +2527,7 @@ nm_connection_get_setting_proxy (NMConnection *connection)
 NMSettingSerial *
 nm_connection_get_setting_serial (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingSerial *) nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_SERIAL);
 }
 
 /**
@@ -2381,9 +2543,7 @@ nm_connection_get_setting_serial (NMConnection *connection)
 NMSettingTun *
 nm_connection_get_setting_tun (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingTun *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TUN);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_TUN);
 }
 
 /**
@@ -2397,9 +2557,7 @@ nm_connection_get_setting_tun (NMConnection *connection)
 NMSettingVpn *
 nm_connection_get_setting_vpn (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingVpn *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_VPN);
 }
 
 /**
@@ -2415,9 +2573,7 @@ nm_connection_get_setting_vpn (NMConnection *connection)
 NMSettingVxlan *
 nm_connection_get_setting_vxlan (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingVxlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VXLAN);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_VXLAN);
 }
 
 /**
@@ -2431,9 +2587,7 @@ nm_connection_get_setting_vxlan (NMConnection *connection)
 NMSettingWimax *
 nm_connection_get_setting_wimax (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_WIMAX);
 }
 
 /**
@@ -2447,9 +2601,7 @@ nm_connection_get_setting_wimax (NMConnection *connection)
 NMSettingWired *
 nm_connection_get_setting_wired (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_WIRED);
 }
 
 /**
@@ -2463,9 +2615,7 @@ nm_connection_get_setting_wired (NMConnection *connection)
 NMSettingAdsl *
 nm_connection_get_setting_adsl (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_ADSL);
 }
 
 /**
@@ -2479,9 +2629,7 @@ nm_connection_get_setting_adsl (NMConnection *connection)
 NMSettingWireless *
 nm_connection_get_setting_wireless (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_WIRELESS);
 }
 
 /**
@@ -2495,9 +2643,7 @@ nm_connection_get_setting_wireless (NMConnection *connection)
 NMSettingWirelessSecurity *
 nm_connection_get_setting_wireless_security (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
 }
 
 /**
@@ -2511,9 +2657,7 @@ nm_connection_get_setting_wireless_security (NMConnection *connection)
 NMSettingBridgePort *
 nm_connection_get_setting_bridge_port (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
-
-	return (NMSettingBridgePort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE_PORT);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_BRIDGE_PORT);
 }
 
 /**
@@ -2527,9 +2671,18 @@ nm_connection_get_setting_bridge_port (NMConnection *connection)
 NMSettingVlan *
 nm_connection_get_setting_vlan (NMConnection *connection)
 {
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+	return _connection_get_setting_check (connection, NM_TYPE_SETTING_VLAN);
+}
+
+NMSettingBluetooth *
+_nm_connection_get_setting_bluetooth_for_nap (NMConnection *connection)
+{
+	NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (connection);
 
-	return (NMSettingVlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VLAN);
+	if (   s_bt
+	    && nm_streq0 (nm_setting_bluetooth_get_connection_type (s_bt), NM_SETTING_BLUETOOTH_TYPE_NAP))
+		return s_bt;
+	return NULL;
 }
 
 /*****************************************************************************/
@@ -2557,7 +2710,7 @@ nm_connection_get_private (NMConnection *connection)
 	key = NM_CACHED_QUARK ("NMConnectionPrivate");
 
 	priv = g_object_get_qdata ((GObject *) connection, key);
-	if (!priv) {
+	if (G_UNLIKELY (!priv)) {
 		priv = g_slice_new0 (NMConnectionPrivate);
 		g_object_set_qdata_full ((GObject *) connection, key,
 		                         priv, (GDestroyNotify) nm_connection_private_free);