about summary refs log tree commit diff
path: root/src/settings/nm-settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/nm-settings.c')
-rw-r--r--src/settings/nm-settings.c278
1 files changed, 111 insertions, 167 deletions
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 35790a12..afd1b084 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -104,7 +104,7 @@ EXPORT(nm_settings_connection_replace_and_commit)
 #define IFCFG_DIR                    SYSCONFDIR "/sysconfig/network"
 #define CONF_DHCP                    IFCFG_DIR "/dhcp"
 
-#define PLUGIN_MODULE_PATH      "plugin-module-path"
+static NM_CACHED_QUARK_FCN ("plugin-module-path", plugin_module_path_quark)
 
 #if (defined(HOSTNAME_PERSIST_SUSE) + defined(HOSTNAME_PERSIST_SLACKWARE) + defined(HOSTNAME_PERSIST_GENTOO)) > 1
 #error "Can only define one of HOSTNAME_PERSIST_*"
@@ -120,6 +120,9 @@ EXPORT(nm_settings_connection_replace_and_commit)
 #define HOSTNAME_FILE           HOSTNAME_FILE_DEFAULT
 #endif
 
+static NM_CACHED_QUARK_FCN ("default-wired-connection", _default_wired_connection_quark)
+static NM_CACHED_QUARK_FCN ("default-wired-device", _default_wired_device_quark)
+
 /*****************************************************************************/
 
 NM_GOBJECT_PROPERTIES_DEFINE (NMSettings,
@@ -390,35 +393,6 @@ error:
 	g_clear_object (&subject);
 }
 
-static int
-connection_sort (gconstpointer pa, gconstpointer pb)
-{
-	NMConnection *a = NM_CONNECTION (pa);
-	NMSettingConnection *con_a;
-	NMConnection *b = NM_CONNECTION (pb);
-	NMSettingConnection *con_b;
-	guint64 ts_a = 0, ts_b = 0;
-	gboolean can_ac_a, can_ac_b;
-
-	con_a = nm_connection_get_setting_connection (a);
-	g_assert (con_a);
-	con_b = nm_connection_get_setting_connection (b);
-	g_assert (con_b);
-
-	can_ac_a = !!nm_setting_connection_get_autoconnect (con_a);
-	can_ac_b = !!nm_setting_connection_get_autoconnect (con_b);
-	if (can_ac_a != can_ac_b)
-		return can_ac_a ? -1 : 1;
-
-	nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (pa), &ts_a);
-	nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (pb), &ts_b);
-	if (ts_a > ts_b)
-		return -1;
-	else if (ts_a == ts_b)
-		return 0;
-	return 1;
-}
-
 /**
  * nm_settings_get_connections:
  * @self: the #NMSettings
@@ -444,46 +418,98 @@ nm_settings_get_connections (NMSettings *self, guint *out_len)
 
 	priv = NM_SETTINGS_GET_PRIVATE (self);
 
-	if (priv->connections_cached_list) {
+	if (G_LIKELY (priv->connections_cached_list)) {
 		NM_SET_OUT (out_len, g_hash_table_size (priv->connections));
 		return priv->connections_cached_list;
 	}
 
 	l = g_hash_table_size (priv->connections);
 
-	v = g_new (NMSettingsConnection *, l + 1);
+	v = g_new (NMSettingsConnection *, (gsize) l + 1);
 
 	i = 0;
 	g_hash_table_iter_init (&iter, priv->connections);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &con))
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &con)) {
+		nm_assert (i < l);
 		v[i++] = con;
-	v[i] = NULL;
-
+	}
 	nm_assert (i == l);
+	v[i] = NULL;
 
 	NM_SET_OUT (out_len, l);
 	priv->connections_cached_list = v;
 	return v;
 }
 
+/**
+ * nm_settings_get_connections_clone:
+ * @self: the #NMSetting
+ * @out_len: (allow-none): optional output argument
+ * @func: caller-supplied function for filtering connections
+ * @func_data: caller-supplied data passed to @func
+ *
+ * Returns: (transfer container) (element-type NMSettingsConnection):
+ *   an NULL terminated array of #NMSettingsConnection objects that were
+ *   filtered by @func (or all connections if no filter was specified).
+ *   The order is arbitrary.
+ *   Caller is responsible for freeing the returned array with free(),
+ *   the contained values do not need to be unrefed.
+ */
+NMSettingsConnection **
+nm_settings_get_connections_clone (NMSettings *self,
+                                   guint *out_len,
+                                   NMSettingsConnectionFilterFunc func,
+                                   gpointer func_data)
+{
+	NMSettingsConnection *const*list_cached;
+	NMSettingsConnection **list;
+	guint len, i, j;
+
+	g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
+
+	list_cached = nm_settings_get_connections (self, &len);
+
+#if NM_MORE_ASSERTS
+	nm_assert (list_cached);
+	for (i = 0; i < len; i++)
+		nm_assert (NM_IS_SETTINGS_CONNECTION (list_cached[i]));
+	nm_assert (!list_cached[i]);
+#endif
+
+	list = g_new (NMSettingsConnection *, ((gsize) len + 1));
+	if (func) {
+		for (i = 0, j = 0; i < len; i++) {
+			if (func (self, list_cached[i], func_data))
+				list[j++] = list_cached[i];
+		}
+		list[j] = NULL;
+		len = j;
+	} else
+		memcpy (list, list_cached, sizeof (list[0]) * ((gsize) len + 1));
+
+	NM_SET_OUT (out_len, len);
+	return list;
+}
+
 /* Returns a list of NMSettingsConnections.
  * The list is sorted in the order suitable for auto-connecting, i.e.
  * first go connections with autoconnect=yes and most recent timestamp.
- * Caller must free the list with g_slist_free().
+ * Caller must free the list with g_free(), but not the list items.
  */
-GSList *
-nm_settings_get_connections_sorted (NMSettings *self)
+NMSettingsConnection **
+nm_settings_get_connections_sorted (NMSettings *self, guint *out_len)
 {
-	GHashTableIter iter;
-	gpointer data = NULL;
-	GSList *list = NULL;
+	NMSettingsConnection **connections;
+	guint len;
 
 	g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
 
-	g_hash_table_iter_init (&iter, NM_SETTINGS_GET_PRIVATE (self)->connections);
-	while (g_hash_table_iter_next (&iter, NULL, &data))
-		list = g_slist_insert_sorted (list, data, connection_sort);
-	return list;
+	connections = nm_settings_get_connections_clone (self, &len, NULL, NULL);
+	if (len > 1)
+		g_qsort_with_data (connections, len, sizeof (NMSettingsConnection *), nm_settings_connection_cmp_autoconnect_priority_p_with_data, NULL);
+
+	NM_SET_OUT (out_len, len);
+	return connections;
 }
 
 NMSettingsConnection *
@@ -753,7 +779,7 @@ add_plugin (NMSettings *self, NMSettingsPlugin *plugin)
 	              NM_SETTINGS_PLUGIN_INFO, &pinfo,
 	              NULL);
 
-	path = g_object_get_data (G_OBJECT (plugin), PLUGIN_MODULE_PATH);
+	path = g_object_get_qdata (G_OBJECT (plugin), plugin_module_path_quark ());
 
 	_LOGI ("loaded plugin %s: %s%s%s%s", pname, pinfo,
 	       NM_PRINT_FMT_QUOTED (path, " (", path, ")", ""));
@@ -809,8 +835,8 @@ load_plugins (NMSettings *self, const char **plugins, GError **error)
 	gboolean has_no_ibft;
 	gssize idx_no_ibft, idx_ibft;
 
-	idx_ibft    = _nm_utils_strv_find_first ((char **) plugins, -1, "ibft");
-	idx_no_ibft = _nm_utils_strv_find_first ((char **) plugins, -1, "no-ibft");
+	idx_ibft    = nm_utils_strv_find_first ((char **) plugins, -1, "ibft");
+	idx_no_ibft = nm_utils_strv_find_first ((char **) plugins, -1, "no-ibft");
 	has_no_ibft = idx_no_ibft >= 0 && idx_no_ibft > idx_ibft;
 #if WITH_SETTINGS_PLUGIN_IBFT
 	add_ibft = idx_no_ibft < 0 && idx_ibft < 0;
@@ -844,9 +870,9 @@ load_plugins (NMSettings *self, const char **plugins, GError **error)
 			continue;
 		}
 
-		if (_nm_utils_strv_find_first ((char **) plugins,
-		                               iter - plugins,
-		                               pname) >= 0) {
+		if (nm_utils_strv_find_first ((char **) plugins,
+		                              iter - plugins,
+		                              pname) >= 0) {
 			/* the plugin is already mentioned in the list previously.
 			 * Don't load a duplicate. */
 			continue;
@@ -916,7 +942,7 @@ load_plugin:
 				break;
 			}
 
-			g_object_set_data_full (obj, PLUGIN_MODULE_PATH, path, g_free);
+			g_object_set_qdata_full (obj, plugin_module_path_quark (), path, g_free);
 			path = NULL;
 			if (add_plugin (self, NM_SETTINGS_PLUGIN (obj)))
 				list = g_slist_append (list, obj);
@@ -1659,6 +1685,28 @@ nm_settings_set_transient_hostname (NMSettings *self,
 	                   info);
 }
 
+gboolean
+nm_settings_get_transient_hostname (NMSettings *self, char **hostname)
+{
+	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+	GVariant *v_hostname;
+
+	if (!priv->hostname.hostnamed_proxy)
+		return FALSE;
+
+	v_hostname = g_dbus_proxy_get_cached_property (priv->hostname.hostnamed_proxy,
+	                                               "Hostname");
+	if (!v_hostname) {
+		_LOGT ("transient hostname retrieval failed");
+		return FALSE;
+	}
+
+	*hostname = g_variant_dup_string (v_hostname, NULL);
+	g_variant_unref (v_hostname);
+
+	return TRUE;
+}
+
 static gboolean
 write_hostname (NMSettingsPrivate *priv, const char *hostname)
 {
@@ -1935,9 +1983,6 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
 	return FALSE;
 }
 
-#define DEFAULT_WIRED_CONNECTION_TAG "default-wired-connection"
-#define DEFAULT_WIRED_DEVICE_TAG     "default-wired-device"
-
 static void default_wired_clear_tag (NMSettings *self,
                                      NMDevice *device,
                                      NMSettingsConnection *connection,
@@ -1953,7 +1998,7 @@ default_wired_connection_removed_cb (NMSettingsConnection *connection, NMSetting
 	 * wired device to the config file and don't create a new default wired
 	 * connection for that device again.
 	 */
-	device = g_object_get_data (G_OBJECT (connection), DEFAULT_WIRED_DEVICE_TAG);
+	device = g_object_get_qdata (G_OBJECT (connection), _default_wired_device_quark ());
 	if (device)
 		default_wired_clear_tag (self, device, connection, TRUE);
 }
@@ -1970,7 +2015,7 @@ default_wired_connection_updated_by_user_cb (NMSettingsConnection *connection, g
 	 * considered a default wired connection, and should no longer affect
 	 * the no-auto-default configuration option.
 	 */
-	device = g_object_get_data (G_OBJECT (connection), DEFAULT_WIRED_DEVICE_TAG);
+	device = g_object_get_qdata (G_OBJECT (connection), _default_wired_device_quark ());
 	if (device)
 		default_wired_clear_tag (self, device, connection, FALSE);
 }
@@ -1984,11 +2029,11 @@ default_wired_clear_tag (NMSettings *self,
 	g_return_if_fail (NM_IS_SETTINGS (self));
 	g_return_if_fail (NM_IS_DEVICE (device));
 	g_return_if_fail (NM_IS_CONNECTION (connection));
-	g_return_if_fail (device == g_object_get_data (G_OBJECT (connection), DEFAULT_WIRED_DEVICE_TAG));
-	g_return_if_fail (connection == g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG));
+	g_return_if_fail (device == g_object_get_qdata (G_OBJECT (connection), _default_wired_device_quark ()));
+	g_return_if_fail (connection == g_object_get_qdata (G_OBJECT (device), _default_wired_connection_quark ()));
 
-	g_object_set_data (G_OBJECT (connection), DEFAULT_WIRED_DEVICE_TAG, NULL);
-	g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG, NULL);
+	g_object_set_qdata (G_OBJECT (connection), _default_wired_device_quark (), NULL);
+	g_object_set_qdata (G_OBJECT (device), _default_wired_connection_quark (), NULL);
 
 	g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_removed_cb), self);
 	g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_updated_by_user_cb), self);
@@ -2015,7 +2060,7 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
 	 * ignore it.
 	 */
 	if (   !nm_device_get_managed (device, FALSE)
-	    || g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG)
+	    || g_object_get_qdata (G_OBJECT (device), _default_wired_connection_quark ())
 	    || have_connection_for_device (self, device))
 		return;
 
@@ -2037,8 +2082,8 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
 		return;
 	}
 
-	g_object_set_data (G_OBJECT (added), DEFAULT_WIRED_DEVICE_TAG, device);
-	g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG, added);
+	g_object_set_qdata (G_OBJECT (added), _default_wired_device_quark (), device);
+	g_object_set_qdata (G_OBJECT (device), _default_wired_connection_quark (), added);
 
 	g_signal_connect (added, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL,
 	                  G_CALLBACK (default_wired_connection_updated_by_user_cb), self);
@@ -2071,7 +2116,7 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quittin
 	                                      G_CALLBACK (device_realized),
 	                                      self);
 
-	connection = g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG);
+	connection = g_object_get_qdata (G_OBJECT (device), _default_wired_connection_quark ());
 	if (connection) {
 		default_wired_clear_tag (self, device, connection, FALSE);
 
@@ -2085,107 +2130,6 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quittin
 
 /*****************************************************************************/
 
-/* GCompareFunc helper for sorting "best" connections.
- * The function sorts connections in ascending timestamp order.
- * That means an older connection (lower timestamp) goes before
- * a newer one.
- */
-gint
-nm_settings_sort_connections (gconstpointer a, gconstpointer b)
-{
-	NMSettingsConnection *ac = (NMSettingsConnection *) a;
-	NMSettingsConnection *bc = (NMSettingsConnection *) b;
-	guint64 ats = 0, bts = 0;
-
-	if (ac == bc)
-		return 0;
-	if (!ac)
-		return -1;
-	if (!bc)
-		return 1;
-
-	/* In the future we may use connection priorities in addition to timestamps */
-	nm_settings_connection_get_timestamp (ac, &ats);
-	nm_settings_connection_get_timestamp (bc, &bts);
-
-	if (ats < bts)
-		return -1;
-	else if (ats > bts)
-		return 1;
-	return 0;
-}
-
-/**
- * nm_settings_get_best_connections:
- * @self: the #NMSetting
- * @max_requested: if non-zero, the maximum number of connections to return
- * @ctype1: an #NMSetting base type (eg NM_SETTING_WIRELESS_SETTING_NAME) to
- *   filter connections against
- * @ctype2: a second #NMSetting base type (eg NM_SETTING_WIRELESS_SETTING_NAME)
- *   to filter connections against
- * @func: caller-supplied function for filtering connections
- * @func_data: caller-supplied data passed to @func
- *
- * Returns: a #GSList of #NMConnection objects in sorted order representing the
- *   "best" or highest-priority connections filtered by @ctype1 and/or @ctype2,
- *   and/or @func.  Caller is responsible for freeing the returned #GSList, but
- *   the contained values do not need to be unreffed.
- */
-GSList *
-nm_settings_get_best_connections (NMSettings *self,
-                                  guint max_requested,
-                                  const char *ctype1,
-                                  const char *ctype2,
-                                  NMConnectionFilterFunc func,
-                                  gpointer func_data)
-{
-	NMSettingsPrivate *priv;
-	GSList *sorted = NULL;
-	GHashTableIter iter;
-	NMSettingsConnection *connection;
-	guint added = 0;
-	guint64 oldest = 0;
-
-	g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
-
-	priv = NM_SETTINGS_GET_PRIVATE (self);
-
-	g_hash_table_iter_init (&iter, priv->connections);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) {
-		guint64 cur_ts = 0;
-
-		if (ctype1 && !nm_connection_is_type (NM_CONNECTION (connection), ctype1))
-			continue;
-		if (ctype2 && !nm_connection_is_type (NM_CONNECTION (connection), ctype2))
-			continue;
-		if (func && !func (self, NM_CONNECTION (connection), func_data))
-			continue;
-
-		/* Don't bother with a connection that's older than the oldest one in the list */
-		if (max_requested && added >= max_requested) {
-		    nm_settings_connection_get_timestamp (connection, &cur_ts);
-		    if (cur_ts <= oldest)
-				continue;
-		}
-
-		/* List is sorted with oldest first */
-		sorted = g_slist_insert_sorted (sorted, connection, nm_settings_sort_connections);
-		added++;
-
-		if (max_requested && added > max_requested) {
-			/* Over the limit, remove the oldest one */
-			sorted = g_slist_delete_link (sorted, sorted);
-			added--;
-		}
-
-		nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (sorted->data), &oldest);
-	}
-
-	return g_slist_reverse (sorted);
-}
-
-/*****************************************************************************/
-
 gboolean
 nm_settings_get_startup_complete (NMSettings *self)
 {
@@ -2221,7 +2165,7 @@ hostnamed_properties_changed (GDBusProxy *proxy,
 		g_free (priv->hostname.value);
 		priv->hostname.value = g_strdup (hostname);
 		_notify (self, PROP_HOSTNAME);
-		nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL);
+		nm_dispatcher_call_hostname (NULL, NULL, NULL);
 	}
 
 	g_variant_unref (v_hostname);