diff options
Diffstat (limited to 'src/dns/nm-dns-systemd-resolved.c')
| -rw-r--r-- | src/dns/nm-dns-systemd-resolved.c | 289 |
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); } |