summary refs log tree commit diff
path: root/src/dns/nm-dns-systemd-resolved.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dns/nm-dns-systemd-resolved.c')
-rw-r--r--src/dns/nm-dns-systemd-resolved.c289
1 files changed, 130 insertions, 159 deletions
diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c
index 7da27e5f..6ab2ea18 100644
--- a/src/dns/nm-dns-systemd-resolved.c
+++ b/src/dns/nm-dns-systemd-resolved.c
@@ -31,15 +31,13 @@
 #include <sys/stat.h>
 #include <linux/if.h>
 
-#include "nm-utils/nm-c-list.h"
 #include "nm-core-internal.h"
 #include "platform/nm-platform.h"
 #include "nm-utils.h"
 #include "nm-ip4-config.h"
 #include "nm-ip6-config.h"
-#include "nm-dbus-manager.h"
+#include "nm-bus-manager.h"
 #include "nm-manager.h"
-#include "nm-setting-connection.h"
 #include "devices/nm-device.h"
 #include "NetworkManagerUtils.h"
 
@@ -50,23 +48,17 @@
 
 typedef struct {
 	int ifindex;
-	CList configs_lst_head;
+	GList *configs;
 } InterfaceConfig;
 
-typedef struct {
-	CList request_queue_lst;
-	const char *operation;
-	GVariant *argument;
-} RequestItem;
-
 /*****************************************************************************/
 
 typedef struct {
 	GDBusProxy *resolve;
 	GCancellable *init_cancellable;
 	GCancellable *update_cancellable;
-	GCancellable *mdns_cancellable;
-	CList request_queue_lst_head;
+	GQueue dns_updates;
+	GQueue domain_updates;
 } NMDnsSystemdResolvedPrivate;
 
 struct _NMDnsSystemdResolved {
@@ -90,36 +82,6 @@ G_DEFINE_TYPE (NMDnsSystemdResolved, nm_dns_systemd_resolved, NM_TYPE_DNS_PLUGIN
 /*****************************************************************************/
 
 static void
-_request_item_free (RequestItem *request_item)
-{
-	c_list_unlink_stale (&request_item->request_queue_lst);
-	g_variant_unref (request_item->argument);
-	g_slice_free (RequestItem, request_item);
-}
-
-static void
-_request_item_append (CList *request_queue_lst_head,
-                      const char *operation,
-                      GVariant *argument)
-{
-	RequestItem *request_item;
-
-	request_item = g_slice_new (RequestItem);
-	request_item->operation = operation;
-	request_item->argument = g_variant_ref_sink (argument);
-	c_list_link_tail (request_queue_lst_head, &request_item->request_queue_lst);
-}
-
-/*****************************************************************************/
-
-static void
-_interface_config_free (InterfaceConfig *config)
-{
-	nm_c_list_elem_free_all (&config->configs_lst_head, NULL);
-	g_slice_free (InterfaceConfig, config);
-}
-
-static void
 call_done (GObject *source, GAsyncResult *r, gpointer user_data)
 {
 	GVariant *v;
@@ -127,58 +89,122 @@ call_done (GObject *source, GAsyncResult *r, gpointer user_data)
 	NMDnsSystemdResolved *self = (NMDnsSystemdResolved *) user_data;
 
 	v = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), r, &error);
-	if (!v) {
-		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-			return;
+
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
+
+	if (error != NULL) {
 		_LOGW ("Failed: %s\n", error->message);
 		g_error_free (error);
 	}
 }
 
 static void
+add_interface_configuration (NMDnsSystemdResolved *self,
+                             GArray *interfaces,
+                             const NMDnsIPConfigData *data,
+                             gboolean skip)
+{
+	int i;
+	InterfaceConfig *ic = NULL;
+	int ifindex;
+
+	if (NM_IS_IP4_CONFIG (data->config))
+		ifindex = nm_ip4_config_get_ifindex (data->config);
+	else if (NM_IS_IP6_CONFIG  (data->config))
+		ifindex = nm_ip6_config_get_ifindex (data->config);
+	else
+		g_return_if_reached ();
+
+	for (i = 0; i < interfaces->len; i++) {
+		InterfaceConfig *tic = &g_array_index (interfaces, InterfaceConfig, i);
+		if (ifindex == tic->ifindex) {
+			ic = tic;
+			break;
+		}
+	}
+
+	if (!ic) {
+		g_array_set_size (interfaces, interfaces->len + 1);
+		ic = &g_array_index (interfaces, InterfaceConfig,
+		                     interfaces->len - 1);
+		ic->ifindex = ifindex;
+	}
+
+	if (!skip)
+		ic->configs = g_list_append (ic->configs, data->config);
+}
+
+static void
 update_add_ip_config (NMDnsSystemdResolved *self,
                       GVariantBuilder *dns,
                       GVariantBuilder *domains,
-                      NMIPConfig *config)
+                      gpointer config)
 {
 	int addr_family;
 	gsize addr_size;
 	guint i, n;
-	gboolean is_routing;
-	const char *domain;
+	gboolean route_only;
+
+	if (NM_IS_IP4_CONFIG (config))
+		addr_family = AF_INET;
+	else if (NM_IS_IP6_CONFIG (config))
+		addr_family = AF_INET6;
+	else
+		g_return_if_reached ();
 
-	addr_family = nm_ip_config_get_addr_family (config);
 	addr_size = nm_utils_addr_family_to_size (addr_family);
 
-	n = nm_ip_config_get_num_nameservers (config);
+	n =   addr_family == AF_INET
+	    ? nm_ip4_config_get_num_nameservers (config)
+	    : nm_ip6_config_get_num_nameservers (config);
 	for (i = 0 ; i < n; i++) {
+		in_addr_t ns4;
+		gconstpointer ns;
+
+		if (addr_family == AF_INET) {
+			ns4 = nm_ip4_config_get_nameserver (config, i);
+			ns = &ns4;
+		} else
+			ns = nm_ip6_config_get_nameserver (config, i);
+
 		g_variant_builder_open (dns, G_VARIANT_TYPE ("(iay)"));
 		g_variant_builder_add (dns, "i", addr_family);
 		g_variant_builder_add_value (dns,
 		                             g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
-		                                                        nm_ip_config_get_nameserver (config, i),
+		                                                        ns,
 		                                                        addr_size,
 		                                                        1));
 		g_variant_builder_close (dns);
 	}
 
-	n = nm_ip_config_get_num_searches (config);
+	/* If this link is never the default (e.g. only used for resources on this
+	 * network) add a routing domain. */
+	route_only =   addr_family == AF_INET
+	             ? !nm_ip4_config_best_default_route_get (config)
+	             : !nm_ip6_config_best_default_route_get (config);
+
+	n =   addr_family == AF_INET
+	    ? nm_ip4_config_get_num_searches (config)
+	    : nm_ip6_config_get_num_searches (config);
 	if (n  > 0) {
 		for (i = 0; i < n; i++) {
-			domain = nm_utils_parse_dns_domain (nm_ip_config_get_search (config, i),
-			                                    &is_routing);
 			g_variant_builder_add (domains, "(sb)",
-			                       domain,
-			                       is_routing);
+			                       addr_family == AF_INET
+			                         ? nm_ip4_config_get_search (config, i)
+			                         : nm_ip6_config_get_search (config, i),
+			                       route_only);
 		}
 	} else {
-		n = nm_ip_config_get_num_domains (config);
+		n =   addr_family == AF_INET
+		    ? nm_ip4_config_get_num_domains (config)
+		    : nm_ip6_config_get_num_domains (config);
 		for (i = 0; i < n; i++) {
-			domain = nm_utils_parse_dns_domain (nm_ip_config_get_domain (config, i),
-			                                    &is_routing);
 			g_variant_builder_add (domains, "(sb)",
-			                       domain,
-			                       is_routing);
+			                       addr_family == AF_INET
+			                         ? nm_ip4_config_get_domain (config, i)
+			                         : nm_ip6_config_get_domain (config, i),
+			                       route_only);
 		}
 	}
 }
@@ -187,13 +213,13 @@ static void
 free_pending_updates (NMDnsSystemdResolved *self)
 {
 	NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
-	RequestItem *request_item, *request_item_safe;
+	GVariant *v;
 
-	c_list_for_each_entry_safe (request_item,
-	                            request_item_safe,
-	                            &priv->request_queue_lst_head,
-	                            request_queue_lst)
-		_request_item_free (request_item);
+	while ((v = g_queue_pop_head (&priv->dns_updates)) != NULL)
+		g_variant_unref (v);
+
+	while ((v = g_queue_pop_head (&priv->domain_updates)) != NULL)
+		g_variant_unref (v);
 }
 
 static void
@@ -201,9 +227,7 @@ prepare_one_interface (NMDnsSystemdResolved *self, InterfaceConfig *ic)
 {
 	NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
 	GVariantBuilder dns, domains;
-	NMCListElem *elem;
-	NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
-	const char *mdns_arg = NULL;
+	GList *l;
 
 	g_variant_builder_init (&dns, G_VARIANT_TYPE ("(ia(iay))"));
 	g_variant_builder_add (&dns, "i", ic->ifindex);
@@ -213,50 +237,23 @@ prepare_one_interface (NMDnsSystemdResolved *self, InterfaceConfig *ic)
 	g_variant_builder_add (&domains, "i", ic->ifindex);
 	g_variant_builder_open (&domains, G_VARIANT_TYPE ("a(sb)"));
 
-	c_list_for_each_entry (elem, &ic->configs_lst_head, lst) {
-		NMIPConfig *ip_config = elem->data;
-
-		update_add_ip_config (self, &dns, &domains, ip_config);
-
-		if (NM_IS_IP4_CONFIG (ip_config))
-			mdns = NM_MAX (mdns, nm_ip4_config_mdns_get (NM_IP4_CONFIG (ip_config)));
-	}
+	for (l = ic->configs; l; l = l->next)
+		update_add_ip_config (self, &dns, &domains, l->data);
 
 	g_variant_builder_close (&dns);
 	g_variant_builder_close (&domains);
 
-	switch (mdns) {
-	case NM_SETTING_CONNECTION_MDNS_NO:
-		mdns_arg = "no";
-		break;
-	case NM_SETTING_CONNECTION_MDNS_RESOLVE:
-		mdns_arg = "resolve";
-		break;
-	case NM_SETTING_CONNECTION_MDNS_YES:
-		mdns_arg = "yes";
-		break;
-	case NM_SETTING_CONNECTION_MDNS_DEFAULT:
-		mdns_arg = "";
-		break;
-	}
-	nm_assert (mdns_arg);
-
-	_request_item_append (&priv->request_queue_lst_head,
-	                      "SetLinkDNS",
-	                      g_variant_builder_end (&dns));
-	_request_item_append (&priv->request_queue_lst_head,
-	                      "SetLinkDomains",
-	                      g_variant_builder_end (&domains));
-	_request_item_append (&priv->request_queue_lst_head,
-	                      "SetLinkMulticastDNS",
-	                      g_variant_new ("(is)", ic->ifindex, mdns_arg ?: ""));
+	g_queue_push_tail (&priv->dns_updates,
+	                   g_variant_ref_sink (g_variant_builder_end (&dns)));
+	g_queue_push_tail (&priv->domain_updates,
+	                   g_variant_ref_sink (g_variant_builder_end (&domains)));
 }
 
 static void
 send_updates (NMDnsSystemdResolved *self)
 {
 	NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
-	RequestItem *request_item, *request_item_safe;
+	GVariant *v;
 
 	nm_clear_g_cancellable (&priv->update_cancellable);
 
@@ -265,81 +262,55 @@ send_updates (NMDnsSystemdResolved *self)
 
 	priv->update_cancellable = g_cancellable_new ();
 
-	c_list_for_each_entry_safe (request_item,
-	                            request_item_safe,
-	                            &priv->request_queue_lst_head,
-	                            request_queue_lst) {
-		g_dbus_proxy_call (priv->resolve,
-		                   request_item->operation,
-		                   request_item->argument,
+	while ((v = g_queue_pop_head (&priv->dns_updates)) != NULL) {
+		g_dbus_proxy_call (priv->resolve, "SetLinkDNS", v,
 		                   G_DBUS_CALL_FLAGS_NONE,
-		                   -1,
-		                   priv->update_cancellable,
-		                   call_done,
-		                   self);
-		_request_item_free (request_item);
+		                   -1, priv->update_cancellable, call_done, self);
+		g_variant_unref (v);
+	}
+
+	while ((v = g_queue_pop_head (&priv->domain_updates)) != NULL) {
+		g_dbus_proxy_call (priv->resolve, "SetLinkDomains", v,
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   -1, priv->update_cancellable, call_done, self);
+		g_variant_unref (v);
 	}
 }
 
 static gboolean
 update (NMDnsPlugin *plugin,
+        const GPtrArray *configs,
         const NMGlobalDnsConfig *global_config,
-        const CList *ip_config_lst_head,
         const char *hostname)
 {
 	NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED (plugin);
-	gs_unref_hashtable GHashTable *interfaces = NULL;
-	gs_free gpointer *interfaces_keys = NULL;
-	guint interfaces_len;
+	GArray *interfaces = g_array_new (TRUE, TRUE, sizeof (InterfaceConfig));
 	guint i;
 	int prio, first_prio = 0;
-	NMDnsIPConfigData *ip_data;
-	gboolean is_first = TRUE;
-
-	interfaces = g_hash_table_new_full (nm_direct_hash, NULL,
-	                                    NULL, (GDestroyNotify) _interface_config_free);
 
-	c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) {
+	for (i = 0; i < configs->len; i++) {
+		const NMDnsIPConfigData *data = configs->pdata[i];
 		gboolean skip = FALSE;
-		InterfaceConfig *ic = NULL;
-		int ifindex;
 
-		prio = nm_ip_config_get_dns_priority (ip_data->ip_config);
-		if (is_first) {
-			is_first = FALSE;
+		prio = nm_ip_config_get_dns_priority (data->config);
+		if (i == 0)
 			first_prio = prio;
-		} else if (first_prio < 0 && first_prio != prio)
+		else if (first_prio < 0 && first_prio != prio)
 			skip = TRUE;
-
-		ifindex = ip_data->data->ifindex;
-		nm_assert (ifindex == nm_ip_config_get_ifindex (ip_data->ip_config));
-
-		ic = g_hash_table_lookup (interfaces, GINT_TO_POINTER (ifindex));
-		if (!ic) {
-			ic = g_slice_new (InterfaceConfig);
-			ic->ifindex = ifindex;
-			c_list_init (&ic->configs_lst_head);
-			g_hash_table_insert (interfaces, GINT_TO_POINTER (ifindex), ic);
-		}
-
-		if (!skip) {
-			c_list_link_tail (&ic->configs_lst_head,
-			                  &nm_c_list_elem_new_stale (ip_data->ip_config)->lst);
-		}
+		add_interface_configuration (self, interfaces, data, skip);
 	}
 
 	free_pending_updates (self);
 
-	interfaces_keys = nm_utils_hash_keys_to_array (interfaces,
-	                                               nm_cmp_int2ptr_p_with_data,
-	                                               NULL,
-	                                               &interfaces_len);
-	for (i = 0; i < interfaces_len; i++) {
-		InterfaceConfig *ic = g_hash_table_lookup (interfaces, GINT_TO_POINTER (interfaces_keys[i]));
+	for (i = 0; i < interfaces->len; i++) {
+		InterfaceConfig *ic = &g_array_index (interfaces, InterfaceConfig, i);
 
 		prepare_one_interface (self, ic);
+		g_list_free (ic->configs);
 	}
 
+	g_array_free (interfaces, TRUE);
+
 	send_updates (self);
 
 	return TRUE;
@@ -392,15 +363,16 @@ static void
 nm_dns_systemd_resolved_init (NMDnsSystemdResolved *self)
 {
 	NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
-	NMDBusManager *dbus_mgr;
+	NMBusManager *dbus_mgr;
 	GDBusConnection *connection;
 
-	c_list_init (&priv->request_queue_lst_head);
+	g_queue_init (&priv->dns_updates);
+	g_queue_init (&priv->domain_updates);
 
-	dbus_mgr = nm_dbus_manager_get ();
+	dbus_mgr = nm_bus_manager_get ();
 	g_return_if_fail (dbus_mgr);
 
-	connection = nm_dbus_manager_get_connection (dbus_mgr);
+	connection = nm_bus_manager_get_connection (dbus_mgr);
 	g_return_if_fail (connection);
 
 	priv->init_cancellable = g_cancellable_new ();
@@ -432,7 +404,6 @@ dispose (GObject *object)
 	g_clear_object (&priv->resolve);
 	nm_clear_g_cancellable (&priv->init_cancellable);
 	nm_clear_g_cancellable (&priv->update_cancellable);
-	nm_clear_g_cancellable (&priv->mdns_cancellable);
 
 	G_OBJECT_CLASS (nm_dns_systemd_resolved_parent_class)->dispose (object);
 }