diff options
Diffstat (limited to 'src/dns')
| -rw-r--r-- | src/dns/nm-dns-dnsmasq.c | 344 | ||||
| -rw-r--r-- | src/dns/nm-dns-manager.c | 819 | ||||
| -rw-r--r-- | src/dns/nm-dns-manager.h | 33 | ||||
| -rw-r--r-- | src/dns/nm-dns-plugin.c | 4 | ||||
| -rw-r--r-- | src/dns/nm-dns-plugin.h | 4 | ||||
| -rw-r--r-- | src/dns/nm-dns-systemd-resolved.c | 289 | ||||
| -rw-r--r-- | src/dns/nm-dns-unbound.c | 2 |
7 files changed, 702 insertions, 793 deletions
diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c index d0753078..e6436c79 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/dns/nm-dns-dnsmasq.c @@ -35,7 +35,7 @@ #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 "NetworkManagerUtils.h" #define PIDFILE NMRUNDIR "/dnsmasq.pid" @@ -76,41 +76,54 @@ G_DEFINE_TYPE (NMDnsDnsmasq, nm_dns_dnsmasq, NM_TYPE_DNS_PLUGIN) /*****************************************************************************/ static char ** -get_ip_rdns_domains (NMIPConfig *ip_config) +get_ip4_rdns_domains (NMIP4Config *ip4) { - int addr_family = nm_ip_config_get_addr_family (ip_config); char **strv; GPtrArray *domains = NULL; NMDedupMultiIter ipconf_iter; + const NMPlatformIP4Address *address; + const NMPlatformIP4Route *route; - nm_assert_addr_family (addr_family); + g_return_val_if_fail (ip4 != NULL, NULL); domains = g_ptr_array_sized_new (5); - if (addr_family == AF_INET) { - NMIP4Config *ip4 = (gpointer) ip_config; - const NMPlatformIP4Address *address; - const NMPlatformIP4Route *route; + nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &address) + nm_utils_get_reverse_dns_domains_ip4 (address->address, address->plen, domains); - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &address) - nm_utils_get_reverse_dns_domains_ip4 (address->address, address->plen, domains); + nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) { + if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) + nm_utils_get_reverse_dns_domains_ip4 (route->network, route->plen, domains); + } - nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) { - if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) - nm_utils_get_reverse_dns_domains_ip4 (route->network, route->plen, domains); - } - } else { - NMIP6Config *ip6 = (gpointer) ip_config; - const NMPlatformIP6Address *address; - const NMPlatformIP6Route *route; + /* Terminating NULL so we can use g_strfreev() to free it */ + g_ptr_array_add (domains, NULL); - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &address) - nm_utils_get_reverse_dns_domains_ip6 (&address->address, address->plen, domains); + /* Free the array and return NULL if the only element was the ending NULL */ + strv = (char **) g_ptr_array_free (domains, (domains->len == 1)); - nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) { - if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) - nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains); - } + return _nm_utils_strv_cleanup (strv, FALSE, FALSE, TRUE); +} + +static char ** +get_ip6_rdns_domains (NMIP6Config *ip6) +{ + char **strv; + GPtrArray *domains = NULL; + NMDedupMultiIter ipconf_iter; + const NMPlatformIP6Address *address; + const NMPlatformIP6Route *route; + + g_return_val_if_fail (ip6 != NULL, NULL); + + domains = g_ptr_array_sized_new (5); + + nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &address) + nm_utils_get_reverse_dns_domains_ip6 (&address->address, address->plen, domains); + + nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) { + if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) + nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains); } /* Terminating NULL so we can use g_strfreev() to free it */ @@ -142,43 +155,96 @@ add_dnsmasq_nameserver (NMDnsDnsmasq *self, g_variant_builder_close (servers); } -#define IP_ADDR_TO_STRING_BUFLEN (NM_UTILS_INET_ADDRSTRLEN + 1 + IFNAMSIZ) - -static const char * -ip_addr_to_string (int addr_family, gconstpointer addr, const char *iface, char *out_buf) +static gboolean +add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, + const char *iface, gboolean split) { - int n_written; - char buf2[NM_UTILS_INET_ADDRSTRLEN]; - const char *separator; + char buf[INET_ADDRSTRLEN + 1 + IFNAMSIZ]; + char buf2[INET_ADDRSTRLEN]; + in_addr_t addr; + int nnameservers, i_nameserver, n, i; + gboolean added = FALSE; - nm_assert_addr_family (addr_family); - nm_assert (addr); - nm_assert (out_buf); + g_return_val_if_fail (iface, FALSE); + nnameservers = nm_ip4_config_get_num_nameservers (ip4); - if (addr_family == AF_INET) { - nm_utils_inet_ntop (addr_family, addr, buf2); - separator = "@"; - } else { - if (IN6_IS_ADDR_V4MAPPED (addr)) - nm_utils_inet4_ntop (((const struct in6_addr *) addr)->s6_addr32[3], buf2); - else - nm_utils_inet6_ntop (addr, buf2); - /* Need to scope link-local addresses with %<zone-id>. Before dnsmasq 2.58, - * only '@' was supported as delimiter. Since 2.58, '@' and '%' are - * supported. Due to a bug, since 2.73 only '%' works properly as "server" - * address. - */ - separator = IN6_IS_ADDR_LINKLOCAL (addr) ? "%" : "@"; + if (split) { + char **domains, **iter; + + if (nnameservers == 0) + return FALSE; + + for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { + addr = nm_ip4_config_get_nameserver (ip4, i_nameserver); + g_snprintf (buf, sizeof (buf), "%s@%s", + nm_utils_inet4_ntop (addr, buf2), iface); + + /* searches are preferred over domains */ + n = nm_ip4_config_get_num_searches (ip4); + for (i = 0; i < n; i++) { + add_dnsmasq_nameserver (self, + servers, + buf, + nm_ip4_config_get_search (ip4, i)); + added = TRUE; + } + + if (n == 0) { + /* If not searches, use any domains */ + n = nm_ip4_config_get_num_domains (ip4); + for (i = 0; i < n; i++) { + add_dnsmasq_nameserver (self, + servers, + buf, + nm_ip4_config_get_domain (ip4, i)); + added = TRUE; + } + } + + /* Ensure reverse-DNS works by directing queries for in-addr.arpa + * domains to the split domain's nameserver. + */ + domains = get_ip4_rdns_domains (ip4); + if (domains) { + for (iter = domains; iter && *iter; iter++) + add_dnsmasq_nameserver (self, servers, buf, *iter); + g_strfreev (domains); + } + } + } + + /* If no searches or domains, just add the nameservers */ + if (!added) { + for (i = 0; i < nnameservers; i++) { + addr = nm_ip4_config_get_nameserver (ip4, i); + g_snprintf (buf, sizeof (buf), "%s@%s", + nm_utils_inet4_ntop (addr, buf2), iface); + add_dnsmasq_nameserver (self, servers, buf, NULL); + } } - n_written = g_snprintf (out_buf, - IP_ADDR_TO_STRING_BUFLEN, - "%s%s%s", - buf2, - iface ? separator : "", - iface ?: ""); - nm_assert (n_written < IP_ADDR_TO_STRING_BUFLEN); - return out_buf; + return TRUE; +} + +static char * +ip6_addr_to_string (const struct in6_addr *addr, const char *iface) +{ + char buf[NM_UTILS_INET_ADDRSTRLEN]; + + if (IN6_IS_ADDR_V4MAPPED (addr)) + nm_utils_inet4_ntop (addr->s6_addr32[3], buf); + else + nm_utils_inet6_ntop (addr, buf); + + /* Need to scope link-local addresses with %<zone-id>. Before dnsmasq 2.58, + * only '@' was supported as delimiter. Since 2.58, '@' and '%' are + * supported. Due to a bug, since 2.73 only '%' works properly as "server" + * address. + */ + return g_strdup_printf ("%s%c%s", + buf, + IN6_IS_ADDR_LINKLOCAL (addr) ? '%' : '@', + iface); } static void @@ -205,100 +271,103 @@ add_global_config (NMDnsDnsmasq *self, GVariantBuilder *dnsmasq_servers, const N } } -static void -add_ip_config (NMDnsDnsmasq *self, - GVariantBuilder *servers, - int ifindex, - NMIPConfig *ip_config, - gboolean split) +static gboolean +add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, + const char *iface, gboolean split) { - int addr_family; - gconstpointer addr; + const struct in6_addr *addr; + char *buf = NULL; + int nnameservers, i_nameserver, n, i; gboolean added = FALSE; - guint nnameservers, i_nameserver, n, i; - char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN]; - char **domains, **iter; - gboolean iface_resolved = FALSE; - const char *iface = NULL, *domain; - addr_family = nm_ip_config_get_addr_family (ip_config); - g_return_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - - nm_assert (ifindex > 0); - nm_assert (ifindex == nm_ip_config_get_ifindex (ip_config)); - - nnameservers = nm_ip_config_get_num_nameservers (ip_config); + g_return_val_if_fail (iface, FALSE); + nnameservers = nm_ip6_config_get_num_nameservers (ip6); if (split) { - if (nnameservers == 0) - return; - - if (!iface_resolved) { - iface = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex); - iface_resolved = TRUE; - } - - if (iface) { - for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { - addr = nm_ip_config_get_nameserver (ip_config, i_nameserver); + char **domains, **iter; - ip_addr_to_string (addr_family, addr, iface, ip_addr_to_string_buf); + if (nnameservers == 0) + return FALSE; + + for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { + addr = nm_ip6_config_get_nameserver (ip6, i_nameserver); + buf = ip6_addr_to_string (addr, iface); + + /* searches are preferred over domains */ + n = nm_ip6_config_get_num_searches (ip6); + for (i = 0; i < n; i++) { + add_dnsmasq_nameserver (self, + servers, + buf, + nm_ip6_config_get_search (ip6, i)); + added = TRUE; + } - /* searches are preferred over domains */ - n = nm_ip_config_get_num_searches (ip_config); + if (n == 0) { + /* If not searches, use any domains */ + n = nm_ip6_config_get_num_domains (ip6); for (i = 0; i < n; i++) { - domain = nm_utils_parse_dns_domain (nm_ip_config_get_search (ip_config, i), NULL); add_dnsmasq_nameserver (self, servers, - ip_addr_to_string_buf, - domain); + buf, + nm_ip6_config_get_domain (ip6, i)); added = TRUE; } + } - if (n == 0) { - /* If not searches, use any domains */ - n = nm_ip_config_get_num_domains (ip_config); - domain = nm_utils_parse_dns_domain (nm_ip_config_get_domain (ip_config, i), NULL); - for (i = 0; i < n; i++) { - add_dnsmasq_nameserver (self, - servers, - ip_addr_to_string_buf, - domain); - added = TRUE; - } - } - - /* Ensure reverse-DNS works by directing queries for in-addr4.arpa/ip6.arpa - * domains to the split domain's nameserver. - */ - domains = get_ip_rdns_domains (ip_config); - if (domains) { - for (iter = domains; *iter; iter++) - add_dnsmasq_nameserver (self, servers, ip_addr_to_string_buf, *iter); - g_strfreev (domains); - } + /* Ensure reverse-DNS works by directing queries for ip6.arpa + * domains to the split domain's nameserver. + */ + domains = get_ip6_rdns_domains (ip6); + if (domains) { + for (iter = domains; iter && *iter; iter++) + add_dnsmasq_nameserver (self, servers, buf, *iter); + g_strfreev (domains); } + + g_free (buf); } } /* If no searches or domains, just add the nameservers */ if (!added) { - if (!iface_resolved) - iface = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex); - if (iface) { - for (i = 0; i < nnameservers; i++) { - addr = nm_ip_config_get_nameserver (ip_config, i); - ip_addr_to_string (addr_family, addr, iface, ip_addr_to_string_buf); - add_dnsmasq_nameserver (self, servers, ip_addr_to_string_buf, NULL); + for (i = 0; i < nnameservers; i++) { + addr = nm_ip6_config_get_nameserver (ip6, i); + buf = ip6_addr_to_string (addr, iface); + if (buf) { + add_dnsmasq_nameserver (self, servers, buf, NULL); + g_free (buf); } } } + + return TRUE; +} + +static gboolean +add_ip_config_data (NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsIPConfigData *data) +{ + if (NM_IS_IP4_CONFIG (data->config)) { + return add_ip4_config (self, + servers, + (NMIP4Config *) data->config, + data->iface, + data->type == NM_DNS_IP_CONFIG_TYPE_VPN); + } else if (NM_IS_IP6_CONFIG (data->config)) { + return add_ip6_config (self, + servers, + (NMIP6Config *) data->config, + data->iface, + data->type == NM_DNS_IP_CONFIG_TYPE_VPN); + } else + g_return_val_if_reached (FALSE); } static void dnsmasq_update_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { NMDnsDnsmasq *self; + NMDnsDnsmasqPrivate *priv; gs_free_error GError *error = NULL; gs_unref_variant GVariant *response = NULL; @@ -307,6 +376,7 @@ dnsmasq_update_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) return; self = NM_DNS_DNSMASQ (user_data); + priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); if (!response) _LOGW ("dnsmasq update failed: %s", error->message); @@ -408,7 +478,7 @@ start_dnsmasq (NMDnsDnsmasq *self) const char *argv[15]; GPid pid = 0; guint idx = 0; - NMDBusManager *dbus_mgr; + NMBusManager *dbus_mgr; GDBusConnection *connection; if (priv->running) { @@ -460,10 +530,10 @@ start_dnsmasq (NMDnsDnsmasq *self) return; } - 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->dnsmasq_cancellable = g_cancellable_new (); @@ -480,16 +550,15 @@ start_dnsmasq (NMDnsDnsmasq *self) static gboolean update (NMDnsPlugin *plugin, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, - const CList *ip_config_lst_head, const char *hostname) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); GVariantBuilder servers; - int prio, first_prio = 0; - const NMDnsIPConfigData *ip_data; - gboolean is_first = TRUE; + guint i; + int prio, first_prio; start_dnsmasq (self); @@ -498,18 +567,15 @@ update (NMDnsPlugin *plugin, if (global_config) add_global_config (self, &servers, global_config); else { - c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) { - prio = nm_ip_config_get_dns_priority (ip_data->ip_config); - if (is_first) { - is_first = FALSE; + for (i = 0; i < configs->len; i++) { + const NMDnsIPConfigData *data = configs->pdata[i]; + + 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) break; - add_ip_config (self, - &servers, - ip_data->data->ifindex, - ip_data->ip_config, - ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN); + add_ip_config_data (self, &servers, data); } } diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 10a16e57..dc545470 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -46,7 +46,6 @@ #include "nm-ip6-config.h" #include "NetworkManagerUtils.h" #include "nm-config.h" -#include "nm-dbus-object.h" #include "devices/nm-device.h" #include "nm-manager.h" @@ -55,6 +54,8 @@ #include "nm-dns-systemd-resolved.h" #include "nm-dns-unbound.h" +#include "introspection/org.freedesktop.NetworkManager.DnsManager.h" + #define HASH_LEN 20 #ifndef RESOLVCONF_PATH @@ -69,24 +70,6 @@ #define PLUGIN_RATELIMIT_BURST 5 #define PLUGIN_RATELIMIT_DELAY 300 -/*****************************************************************************/ - -typedef enum { - SR_SUCCESS, - SR_NOTFOUND, - SR_ERROR -} SpawnResult; - -typedef struct { - GPtrArray *nameservers; - GPtrArray *searches; - GPtrArray *options; - const char *nis_domain; - GPtrArray *nis_servers; -} NMResolvConfData; - -/*****************************************************************************/ - enum { CONFIG_CHANGED, @@ -101,16 +84,44 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDnsManager, static guint signals[LAST_SIGNAL] = { 0 }; -typedef struct { - GHashTable *configs; - CList ip_config_lst_head; - GVariant *config_variant; +typedef enum { + SR_SUCCESS, + SR_NOTFOUND, + SR_ERROR +} SpawnResult; - NMDnsIPConfigData *best_ip_config_4; - NMDnsIPConfigData *best_ip_config_6; +NM_DEFINE_SINGLETON_GETTER (NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER); - bool ip_config_lst_need_sort:1; +/*****************************************************************************/ +#define _NMLOG_PREFIX_NAME "dns-mgr" +#define _NMLOG_DOMAIN LOGD_DNS +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ + char __prefix[20]; \ + const NMDnsManager *const __self = (self); \ + \ + _nm_log (__level, _NMLOG_DOMAIN, 0, NULL, NULL, \ + "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((!__self || __self == singleton_instance) \ + ? "" \ + : nm_sprintf_buf (__prefix, "[%p]", __self)) \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END + +/*****************************************************************************/ + +typedef struct { + GPtrArray *configs; + GVariant *config_variant; + NMDnsIPConfigData *best_conf4, *best_conf6; + + bool need_sort:1; bool dns_touched:1; bool is_stopped:1; @@ -134,52 +145,20 @@ typedef struct { } NMDnsManagerPrivate; struct _NMDnsManager { - NMDBusObject parent; + NMExportedObject parent; NMDnsManagerPrivate _priv; }; struct _NMDnsManagerClass { - NMDBusObjectClass parent; + NMExportedObjectClass parent; }; -G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, NM_TYPE_DBUS_OBJECT) +G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, NM_TYPE_EXPORTED_OBJECT) #define NM_DNS_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDnsManager, NM_IS_DNS_MANAGER) -NM_DEFINE_SINGLETON_GETTER (NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER); - -/*****************************************************************************/ - -#define _NMLOG_PREFIX_NAME "dns-mgr" -#define _NMLOG_DOMAIN LOGD_DNS -#define _NMLOG(level, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ - char __prefix[20]; \ - const NMDnsManager *const __self = (self); \ - \ - _nm_log (__level, _NMLOG_DOMAIN, 0, NULL, NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - ((!__self || __self == singleton_instance) \ - ? "" \ - : nm_sprintf_buf (__prefix, "[%p]", __self)) \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END - -/*****************************************************************************/ - -static void _ip_config_dns_priority_changed (gpointer config, - GParamSpec *pspec, - NMDnsIPConfigData *ip_data); - -/*****************************************************************************/ - static gboolean -domain_is_valid (const char *domain, gboolean check_public_suffix) +domain_is_valid (const gchar *domain, gboolean check_public_suffix) { if (*domain == '\0') return FALSE; @@ -190,14 +169,16 @@ domain_is_valid (const char *domain, gboolean check_public_suffix) return TRUE; } -static gboolean -domain_is_routing (const char *domain) -{ - return domain[0] == '~'; -} - /*****************************************************************************/ +typedef struct { + GPtrArray *nameservers; + GPtrArray *searches; + GPtrArray *options; + const char *nis_domain; + GPtrArray *nis_servers; +} NMResolvConfData; + NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConfManager, NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, "unknown"), @@ -211,109 +192,44 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConf NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_config_type_to_string, NMDnsIPConfigType, NM_UTILS_LOOKUP_DEFAULT_WARN ("<unknown>"), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_REMOVED, "removed"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_DEFAULT, "default"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, "best"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_VPN, "vpn"), ); -/*****************************************************************************/ - -static void -_ASSERT_config_data (const NMDnsConfigData *data) -{ - nm_assert (data); - nm_assert (NM_IS_DNS_MANAGER (data->self)); - nm_assert (data->ifindex > 0); -} - -static void -_ASSERT_ip_config_data (const NMDnsIPConfigData *ip_data) -{ - nm_assert (ip_data); - _ASSERT_config_data (ip_data->data); - nm_assert (NM_IS_IP_CONFIG (ip_data->ip_config)); - nm_assert (c_list_contains (&ip_data->data->data_lst_head, &ip_data->data_lst)); - nm_assert (ip_data->data->ifindex == nm_ip_config_get_ifindex (ip_data->ip_config)); -} - static NMDnsIPConfigData * -_ip_config_data_new (NMDnsConfigData *data, - NMIPConfig *ip_config, - NMDnsIPConfigType ip_config_type) -{ - NMDnsIPConfigData *ip_data; - - _ASSERT_config_data (data); - nm_assert (NM_IS_IP_CONFIG (ip_config)); - nm_assert (ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED); - - ip_data = g_slice_new0 (NMDnsIPConfigData); - ip_data->data = data; - ip_data->ip_config = g_object_ref (ip_config); - ip_data->ip_config_type = ip_config_type; - c_list_link_tail (&data->data_lst_head, &ip_data->data_lst); - c_list_link_tail (&NM_DNS_MANAGER_GET_PRIVATE (data->self)->ip_config_lst_head, &ip_data->ip_config_lst); - - g_signal_connect (ip_config, - NM_IS_IP4_CONFIG (ip_config) - ? "notify::" NM_IP4_CONFIG_DNS_PRIORITY - : "notify::" NM_IP6_CONFIG_DNS_PRIORITY, - (GCallback) _ip_config_dns_priority_changed, ip_data); - - _ASSERT_ip_config_data (ip_data); - return ip_data; -} - -static void -_ip_config_data_free (NMDnsIPConfigData *ip_data) +ip_config_data_new (gpointer config, NMDnsIPConfigType type, const char *iface) { - _ASSERT_ip_config_data (ip_data); + NMDnsIPConfigData *data; - c_list_unlink_stale (&ip_data->data_lst); - c_list_unlink_stale (&ip_data->ip_config_lst); + data = g_slice_new0 (NMDnsIPConfigData); + data->config = g_object_ref (config); + data->iface = g_strdup (iface); + data->type = type; - g_signal_handlers_disconnect_by_func (ip_data->ip_config, - _ip_config_dns_priority_changed, - ip_data); - - g_object_unref (ip_data->ip_config); - g_slice_free (NMDnsIPConfigData, ip_data); -} - -static NMDnsIPConfigData * -_config_data_find_ip_config (NMDnsConfigData *data, - NMIPConfig *ip_config) -{ - NMDnsIPConfigData *ip_data; - - _ASSERT_config_data (data); - - c_list_for_each_entry (ip_data, &data->data_lst_head, data_lst) { - _ASSERT_ip_config_data (ip_data); - - if (ip_data->ip_config == ip_config) - return ip_data; - } - return NULL; + return data; } static void -_config_data_free (NMDnsConfigData *data) +ip_config_data_destroy (gpointer ptr) { - _ASSERT_config_data (data); + NMDnsIPConfigData *data = ptr; + + if (!data) + return; - nm_assert (c_list_is_empty (&data->data_lst_head)); - g_slice_free (NMDnsConfigData, data); + g_object_unref (data->config); + g_free (data->iface); + g_slice_free (NMDnsIPConfigData, data); } static gint -_ip_config_data_cmp (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) +ip_config_data_compare (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) { int a_prio, b_prio; - a_prio = nm_ip_config_get_dns_priority (a->ip_config); - b_prio = nm_ip_config_get_dns_priority (b->ip_config); + a_prio = nm_ip_config_get_dns_priority (a->config); + b_prio = nm_ip_config_get_dns_priority (b->config); /* Configurations with lower priority value first */ if (a_prio < b_prio) @@ -322,40 +238,24 @@ _ip_config_data_cmp (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) return 1; /* Sort also according to type */ - if (a->ip_config_type > b->ip_config_type) + if (a->type > b->type) return -1; - else if (a->ip_config_type < b->ip_config_type) + else if (a->type < b->type) return 1; return 0; } static gint -_ip_config_lst_cmp (const CList *a, - const CList *b, - const void *user_data) +ip_config_data_ptr_compare (gconstpointer a, gconstpointer b) { - return _ip_config_data_cmp (c_list_entry (a, NMDnsIPConfigData, ip_config_lst), - c_list_entry (b, NMDnsIPConfigData, ip_config_lst)); -} + const NMDnsIPConfigData *const *ptr_a = a, *const *ptr_b = b; -static CList * -_ip_config_lst_head (NMDnsManager *self) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - - if (priv->ip_config_lst_need_sort) { - priv->ip_config_lst_need_sort = FALSE; - c_list_sort (&priv->ip_config_lst_head, _ip_config_lst_cmp, NULL); - } - - return &priv->ip_config_lst_head; + return ip_config_data_compare (*ptr_a, *ptr_b); } -/*****************************************************************************/ - static void -add_string_item (GPtrArray *array, const char *str, gboolean dup) +add_string_item (GPtrArray *array, const char *str) { int i; @@ -371,7 +271,7 @@ add_string_item (GPtrArray *array, const char *str, gboolean dup) } /* No dupes, add the new item */ - g_ptr_array_add (array, dup ? g_strdup (str): (gpointer) str); + g_ptr_array_add (array, g_strdup (str)); } static void @@ -382,55 +282,24 @@ add_dns_option_item (GPtrArray *array, const char *str) } static void -add_dns_domains (GPtrArray *array, const NMIPConfig *ip_config, - gboolean include_routing, gboolean dup) -{ - guint num_domains, num_searches, i; - const char *str; - - num_domains = nm_ip_config_get_num_domains (ip_config); - num_searches = nm_ip_config_get_num_searches (ip_config); - - for (i = 0; i < num_searches; i++) { - str = nm_ip_config_get_search (ip_config, i); - if (!include_routing && domain_is_routing (str)) - continue; - if (!domain_is_valid (nm_utils_parse_dns_domain (str, NULL), FALSE)) - continue; - add_string_item (array, str, dup); - } - if (num_domains > 1 || !num_searches) { - for (i = 0; i < num_domains; i++) { - str = nm_ip_config_get_domain (ip_config, i); - if (!include_routing && domain_is_routing (str)) - continue; - if (!domain_is_valid (nm_utils_parse_dns_domain (str, NULL), FALSE)) - continue; - add_string_item (array, str, dup); - } - } -} - -static void merge_one_ip_config (NMResolvConfData *rc, - int ifindex, - const NMIPConfig *ip_config) + const NMIPConfig *config, + const char *iface) { int addr_family; - guint num, i; + guint num, num_domains, num_searches, i; char buf[NM_UTILS_INET_ADDRSTRLEN + 50]; + const char *str; - addr_family = nm_ip_config_get_addr_family (ip_config); + addr_family = nm_ip_config_get_addr_family (config); nm_assert_addr_family (addr_family); - nm_assert (ifindex > 0); - nm_assert (ifindex == nm_ip_config_get_ifindex (ip_config)); - num = nm_ip_config_get_num_nameservers (ip_config); + num = nm_ip_config_get_num_nameservers (config); for (i = 0; i < num; i++) { const NMIPAddr *addr; - addr = nm_ip_config_get_nameserver (ip_config, i); + addr = nm_ip_config_get_nameserver (config, i); if (addr_family == AF_INET) nm_utils_inet_ntop (addr_family, addr, buf); else if (IN6_IS_ADDR_V4MAPPED (addr)) @@ -438,42 +307,49 @@ merge_one_ip_config (NMResolvConfData *rc, else { nm_utils_inet6_ntop (&addr->addr6, buf); if (IN6_IS_ADDR_LINKLOCAL (addr)) { - const char *ifname; - - ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex); - if (ifname) { - g_strlcat (buf, "%", sizeof (buf)); - g_strlcat (buf, ifname, sizeof (buf)); - } + g_strlcat (buf, "%", sizeof (buf)); + g_strlcat (buf, iface, sizeof (buf)); } } - add_string_item (rc->nameservers, buf, TRUE); + add_string_item (rc->nameservers, buf); } - add_dns_domains (rc->searches, ip_config, FALSE, TRUE); + num_domains = nm_ip_config_get_num_domains (config); + num_searches = nm_ip_config_get_num_searches (config); + for (i = 0; i < num_searches; i++) { + str = nm_ip_config_get_search (config, i); + if (domain_is_valid (str, FALSE)) + add_string_item (rc->searches, str); + } + if (num_domains > 1 || !num_searches) { + for (i = 0; i < num_domains; i++) { + str = nm_ip_config_get_domain (config, i); + if (domain_is_valid (str, FALSE)) + add_string_item (rc->searches, str); + } + } - num = nm_ip_config_get_num_dns_options (ip_config); + num = nm_ip_config_get_num_dns_options (config); for (i = 0; i < num; i++) { add_dns_option_item (rc->options, - nm_ip_config_get_dns_option (ip_config, i)); + nm_ip_config_get_dns_option (config, i)); } if (addr_family == AF_INET) { - const NMIP4Config *ip4_config = (const NMIP4Config *) ip_config; + const NMIP4Config *config4 = (const NMIP4Config *) config; /* NIS stuff */ - num = nm_ip4_config_get_num_nis_servers (ip4_config); + num = nm_ip4_config_get_num_nis_servers (config4); for (i = 0; i < num; i++) { add_string_item (rc->nis_servers, - nm_utils_inet4_ntop (nm_ip4_config_get_nis_server (ip4_config, i), buf), - TRUE); + nm_utils_inet4_ntop (nm_ip4_config_get_nis_server (config4, i), buf)); } - if (nm_ip4_config_get_nis_domain (ip4_config)) { + if (nm_ip4_config_get_nis_domain (config4)) { /* FIXME: handle multiple domains */ if (!rc->nis_domain) - rc->nis_domain = nm_ip4_config_get_nis_domain (ip4_config); + rc->nis_domain = nm_ip4_config_get_nis_domain (config4); } } } @@ -502,59 +378,58 @@ run_netconfig (NMDnsManager *self, GError **error, gint *stdin_fd) } static void -netconfig_construct_str (NMDnsManager *self, GString *str, const char *key, const char *value) +write_to_netconfig (NMDnsManager *self, gint fd, const char *key, const char *value) { - if (value) { - _LOGD ("writing to netconfig: %s='%s'", key, value); - g_string_append_printf (str, "%s='%s'\n", key, value); - } -} + char *str; + int x; -static void -netconfig_construct_strv (NMDnsManager *self, GString *str, const char *key, const char *const*values) -{ - if (values) { - gs_free char *value = NULL; - - value = g_strjoinv (" ", (char **) values); - netconfig_construct_str (self, str, key, value); - } + str = g_strdup_printf ("%s='%s'\n", key, value); + _LOGD ("writing to netconfig: %s", str); + x = write (fd, str, strlen (str)); + g_free (str); } static SpawnResult dispatch_netconfig (NMDnsManager *self, - const char *const*searches, - const char *const*nameservers, + char **searches, + char **nameservers, const char *nis_domain, - const char *const*nis_servers, + char **nis_servers, GError **error) { + char *str; GPid pid; gint fd; int status; - gssize l; - nm_auto_free_gstring GString *str = NULL; pid = run_netconfig (self, error, &fd); if (pid <= 0) return SR_NOTFOUND; - str = g_string_new (""); - /* NM is writing already-merged DNS information to netconfig, so it * does not apply to a specific network interface. */ - netconfig_construct_str (self, str, "INTERFACE", "NetworkManager"); - netconfig_construct_strv (self, str, "DNSSEARCH", searches); - netconfig_construct_strv (self, str, "DNSSERVERS", nameservers); - netconfig_construct_str (self, str, "NISDOMAIN", nis_domain); - netconfig_construct_strv (self, str, "NISSERVERS", nis_servers); + write_to_netconfig (self, fd, "INTERFACE", "NetworkManager"); -again: - l = write (fd, str->str, str->len); - if (l == -1) { - if (errno == EINTR) - goto again; + if (searches) { + str = g_strjoinv (" ", searches); + write_to_netconfig (self, fd, "DNSSEARCH", str); + g_free (str); + } + + if (nameservers) { + str = g_strjoinv (" ", nameservers); + write_to_netconfig (self, fd, "DNSSERVERS", str); + g_free (str); + } + + if (nis_domain) + write_to_netconfig (self, fd, "NISDOMAIN", nis_domain); + + if (nis_servers) { + str = g_strjoinv (" ", nis_servers); + write_to_netconfig (self, fd, "NISSERVERS", str); + g_free (str); } nm_close (fd); @@ -868,7 +743,7 @@ update_resolv_conf (NMDnsManager *self, if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) { _LOGT ("update-resolv-conf: write internal file %s succeeded (rc-manager=%s)", - MY_RESOLV_CONF, _rc_manager_to_string (rc_manager)); + rc_path, _rc_manager_to_string (rc_manager)); return write_file_result; } @@ -942,21 +817,25 @@ update_resolv_conf (NMDnsManager *self, static void compute_hash (NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[HASH_LEN]) { + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); GChecksum *sum; gsize len = HASH_LEN; - NMDnsIPConfigData *ip_data; + guint i; sum = g_checksum_new (G_CHECKSUM_SHA1); - nm_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); + g_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); if (global) nm_global_dns_config_update_checksum (global, sum); else { - const CList *head; + for (i = 0; i < priv->configs->len; i++) { + NMDnsIPConfigData *data = priv->configs->pdata[i]; - head = _ip_config_lst_head (self); - c_list_for_each_entry (ip_data, head, ip_config_lst) - nm_ip_config_hash (ip_data->ip_config, sum, TRUE); + if (NM_IS_IP4_CONFIG (data->config)) + nm_ip4_config_hash ((NMIP4Config *) data->config, sum, TRUE); + else if (NM_IS_IP6_CONFIG (data->config)) + nm_ip6_config_hash ((NMIP6Config *) data->config, sum, TRUE); + } } g_checksum_get_digest (sum, buffer, &len); @@ -970,36 +849,27 @@ merge_global_dns_config (NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) const char *const *searches; const char *const *options; const char *const *servers; - guint i; + gint i; if (!global_conf) return FALSE; searches = nm_global_dns_config_get_searches (global_conf); - if (searches) { - for (i = 0; searches[i]; i++) { - if (domain_is_routing (searches[i])) - continue; - if (!domain_is_valid (searches[i], FALSE)) - continue; - add_string_item (rc->searches, searches[i], TRUE); - } - } - options = nm_global_dns_config_get_options (global_conf); - if (options) { - for (i = 0; options[i]; i++) - add_string_item (rc->options, options[i], TRUE); + + for (i = 0; searches && searches[i]; i++) { + if (domain_is_valid (searches[i], FALSE)) + add_string_item (rc->searches, searches[i]); } - default_domain = nm_global_dns_config_lookup_domain (global_conf, "*"); - nm_assert (default_domain); + for (i = 0; options && options[i]; i++) + add_string_item (rc->options, options[i]); + default_domain = nm_global_dns_config_lookup_domain (global_conf, "*"); + g_assert (default_domain); servers = nm_global_dns_domain_get_servers (default_domain); - if (servers) { - for (i = 0; servers[i]; i++) - add_string_item (rc->nameservers, servers[i], TRUE); - } + for (i = 0; servers && servers[i]; i++) + add_string_item (rc->nameservers, servers[i]); return TRUE; } @@ -1039,16 +909,17 @@ _ptrarray_to_strv (GPtrArray *parray) } static void -_collect_resolv_conf_data (NMDnsManager *self, +_collect_resolv_conf_data (NMDnsManager *self, /* only for logging context, no other side-effects */ NMGlobalDnsConfig *global_config, + const GPtrArray *configs, + const char *hostname, char ***out_searches, char ***out_options, char ***out_nameservers, char ***out_nis_servers, const char **out_nis_domain) { - NMDnsManagerPrivate *priv; - guint i, num, len; + guint i, j, num, len; NMResolvConfData rc = { .nameservers = g_ptr_array_new (), .searches = g_ptr_array_new (), @@ -1057,44 +928,37 @@ _collect_resolv_conf_data (NMDnsManager *self, .nis_servers = g_ptr_array_new (), }; - priv = NM_DNS_MANAGER_GET_PRIVATE (self); - if (global_config) merge_global_dns_config (&rc, global_config); else { nm_auto_free_gstring GString *tmp_gstring = NULL; int prio, first_prio = 0; - const NMDnsIPConfigData *ip_data; - const CList *head; - gboolean is_first = TRUE; + NMDnsIPConfigData *current; - head = _ip_config_lst_head (self); - c_list_for_each_entry (ip_data, head, ip_config_lst) { + for (i = 0, j = 0; i < configs->len; i++) { gboolean skip = FALSE; - _ASSERT_ip_config_data (ip_data); + current = configs->pdata[i]; - prio = nm_ip_config_get_dns_priority (ip_data->ip_config); + prio = nm_ip_config_get_dns_priority (current->config); - if (is_first) { - is_first = FALSE; + if (i == 0) first_prio = prio; - } else if ( first_prio < 0 - && first_prio != prio) + else if (first_prio < 0 && first_prio != prio) skip = TRUE; - if (nm_ip_config_get_num_nameservers (ip_data->ip_config)) { - _LOGT ("config: %8d %-7s v%c %-5d %s: %s", + if (nm_ip_config_get_num_nameservers (current->config)) { + _LOGT ("config: %8d %-7s v%c %-16s %s: %s", prio, - _config_type_to_string (ip_data->ip_config_type), - nm_utils_addr_family_to_char (nm_ip_config_get_addr_family (ip_data->ip_config)), - ip_data->data->ifindex, + _config_type_to_string (current->type), + nm_utils_addr_family_to_char (nm_ip_config_get_addr_family (current->config)), + current->iface, skip ? "<SKIP>" : "", - get_nameserver_list (ip_data->ip_config, &tmp_gstring)); + get_nameserver_list (current->config, &tmp_gstring)); } if (!skip) - merge_one_ip_config (&rc, ip_data->data->ifindex, ip_data->ip_config); + merge_one_ip_config (&rc, current->config, current->iface); } } @@ -1105,16 +969,16 @@ _collect_resolv_conf_data (NMDnsManager *self, * (eg, "example.com"), then use the hostname itself as the search (since the user is * unlikely to want "com" as a search domain). */ - if (priv->hostname) { - const char *hostdomain = strchr (priv->hostname, '.'); + if (hostname) { + const char *hostdomain = strchr (hostname, '.'); if ( hostdomain - && !nm_utils_ipaddr_valid (AF_UNSPEC, priv->hostname)) { + && !nm_utils_ipaddr_valid (AF_UNSPEC, hostname)) { hostdomain++; if (domain_is_valid (hostdomain, TRUE)) - add_string_item (rc.searches, hostdomain, TRUE); - else if (domain_is_valid (priv->hostname, TRUE)) - add_string_item (rc.searches, priv->hostname, TRUE); + add_string_item (rc.searches, hostdomain); + else if (domain_is_valid (hostname, TRUE)) + add_string_item (rc.searches, hostname); } } @@ -1176,12 +1040,16 @@ update_dns (NMDnsManager *self, data = nm_config_get_data (priv->config); global_config = nm_config_data_get_global_dns_config (data); + if (priv->need_sort) { + g_ptr_array_sort (priv->configs, ip_config_data_ptr_compare); + priv->need_sort = FALSE; + } + /* Update hash with config we're applying */ compute_hash (self, global_config, priv->hash); - _collect_resolv_conf_data (self, global_config, - &searches, &options, &nameservers, - &nis_servers, &nis_domain); + _collect_resolv_conf_data (self, global_config, priv->configs, priv->hostname, + &searches, &options, &nameservers, &nis_servers, &nis_domain); /* Let any plugins do their thing first */ if (priv->plugin) { @@ -1199,8 +1067,8 @@ update_dns (NMDnsManager *self, _LOGD ("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update (plugin, + priv->configs, global_config, - _ip_config_lst_head (self), priv->hostname)) { _LOGW ("update-dns: plugin %s update failed", plugin_name); @@ -1246,12 +1114,8 @@ update_dns (NMDnsManager *self, result = dispatch_resolvconf (self, searches, nameservers, options, error); break; case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: - result = dispatch_netconfig (self, - (const char *const*) searches, - (const char *const*) nameservers, - nis_domain, - (const char *const*) nis_servers, - error); + result = dispatch_netconfig (self, searches, nameservers, nis_domain, + nis_servers, error); break; default: g_assert_not_reached (); @@ -1341,96 +1205,82 @@ plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data) } static void -_ip_config_dns_priority_changed (gpointer config, - GParamSpec *pspec, - NMDnsIPConfigData *ip_data) +ip_config_dns_priority_changed (gpointer config, + GParamSpec *pspec, + NMDnsManager *self) { - _ASSERT_ip_config_data (ip_data); + NM_DNS_MANAGER_GET_PRIVATE (self)->need_sort = TRUE; +} - NM_DNS_MANAGER_GET_PRIVATE (ip_data->data->self)->ip_config_lst_need_sort = TRUE; +static void +forget_data (NMDnsManager *self, NMDnsIPConfigData *data) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + if (data == priv->best_conf4) + priv->best_conf4 = NULL; + else if (data == priv->best_conf6) + priv->best_conf6 = NULL; + + g_signal_handlers_disconnect_by_func (data->config, ip_config_dns_priority_changed, self); } gboolean -nm_dns_manager_set_ip_config (NMDnsManager *self, - NMIPConfig *ip_config, - NMDnsIPConfigType ip_config_type) +nm_dns_manager_add_ip_config (NMDnsManager *self, + const char *iface, + gpointer config, + NMDnsIPConfigType cfg_type) { NMDnsManagerPrivate *priv; GError *error = NULL; - NMDnsIPConfigData *ip_data; - NMDnsConfigData *data; - int ifindex; - NMDnsIPConfigData **p_best; + NMDnsIPConfigData *data; + gboolean v4 = NM_IS_IP4_CONFIG (config); + guint i; g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); - g_return_val_if_fail (NM_IS_IP_CONFIG (ip_config), FALSE); - - ifindex = nm_ip_config_get_ifindex (ip_config); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (config, FALSE); + g_return_val_if_fail (iface && iface[0], FALSE); + nm_assert (NM_IS_IP_CONFIG (config)); priv = NM_DNS_MANAGER_GET_PRIVATE (self); - data = g_hash_table_lookup (priv->configs, GINT_TO_POINTER (ifindex)); - if (!data) - ip_data = NULL; - else - ip_data = _config_data_find_ip_config (data, ip_config); - - if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED) { - if (!ip_data) - return FALSE; - if (priv->best_ip_config_4 == ip_data) - priv->best_ip_config_4 = NULL; - if (priv->best_ip_config_6 == ip_data) - priv->best_ip_config_6 = NULL; - /* deleting a config doesn't invalidate the configs' sort order. */ - _ip_config_data_free (ip_data); - if (c_list_is_empty (&data->data_lst_head)) - g_hash_table_remove (priv->configs, GINT_TO_POINTER (ifindex)); - goto changed; - } - - if ( ip_data - && ip_data->ip_config_type == ip_config_type) { - /* nothing to do. */ - return FALSE; - } - - if (!data) { - data = g_slice_new0 (NMDnsConfigData); - data->ifindex = ifindex; - data->self = self; - c_list_init (&data->data_lst_head); - _ASSERT_config_data (data); - g_hash_table_insert (priv->configs, GINT_TO_POINTER (ifindex), data); + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + if (data->config == config) { + if ( nm_streq (data->iface, iface) + && data->type == cfg_type) + return FALSE; + else { + forget_data (self, data); + g_ptr_array_remove_index_fast (priv->configs, i); + break; + } + } } - if (!ip_data) - ip_data = _ip_config_data_new (data, ip_config, ip_config_type); - else - ip_data->ip_config_type = ip_config_type; - - priv->ip_config_lst_need_sort = TRUE; - - p_best = NM_IS_IP4_CONFIG (ip_config) - ? &priv->best_ip_config_4 - : &priv->best_ip_config_6; + data = ip_config_data_new (config, cfg_type, iface); + g_ptr_array_add (priv->configs, data); + g_signal_connect (config, + v4 ? + "notify::" NM_IP4_CONFIG_DNS_PRIORITY : + "notify::" NM_IP6_CONFIG_DNS_PRIORITY, + (GCallback) ip_config_dns_priority_changed, self); + priv->need_sort = TRUE; - if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) { + if (cfg_type == NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) { /* Only one best-device per IP version is allowed */ - if (*p_best != ip_data) { - if (*p_best) - (*p_best)->ip_config_type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; - *p_best = ip_data; + if (v4) { + if (priv->best_conf4) + priv->best_conf4->type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; + priv->best_conf4 = data; + } else { + if (priv->best_conf6) + priv->best_conf6->type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; + priv->best_conf6 = data; } - } else { - if (*p_best == ip_data) - *p_best = NULL; } -changed: - if ( !priv->updates_queue - && !update_dns (self, FALSE, &error)) { + if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { _LOGW ("could not commit DNS changes: %s", error->message); g_clear_error (&error); } @@ -1438,6 +1288,38 @@ changed: return TRUE; } +gboolean +nm_dns_manager_remove_ip_config (NMDnsManager *self, gpointer config) +{ + NMDnsManagerPrivate *priv; + GError *error = NULL; + NMDnsIPConfigData *data; + guint i; + + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + g_return_val_if_fail (config, FALSE); + nm_assert (NM_IS_IP_CONFIG (config)); + + priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + + if (data->config == config) { + forget_data (self, data); + g_ptr_array_remove_index (priv->configs, i); + + if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { + _LOGW ("could not commit DNS changes: %s", error->message); + g_clear_error (&error); + } + + return TRUE; + } + } + return FALSE; +} + void nm_dns_manager_set_initial_hostname (NMDnsManager *self, const char *hostname) @@ -1480,6 +1362,23 @@ nm_dns_manager_set_hostname (NMDnsManager *self, } } +gboolean +nm_dns_manager_get_resolv_conf_explicit (NMDnsManager *self) +{ + NMDnsManagerPrivate *priv; + + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + + priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + if ( NM_IN_SET (priv->rc_manager, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE) + || priv->plugin) + return FALSE; + + return TRUE; +} + void nm_dns_manager_begin_updates (NMDnsManager *self, const char *func) { @@ -1510,6 +1409,11 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) priv = NM_DNS_MANAGER_GET_PRIVATE (self); g_return_if_fail (priv->updates_queue > 0); + if (priv->need_sort) { + g_ptr_array_sort (priv->configs, ip_config_data_ptr_compare); + priv->need_sort = FALSE; + } + compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)), new); changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE; _LOGD ("(%s): DNS configuration %s", func, changed ? "changed" : "did not change"); @@ -1906,14 +1810,14 @@ _get_config_variant (NMDnsManager *self) NMGlobalDnsConfig *global_config; gs_free char *str = NULL; GVariantBuilder builder; - NMDnsIPConfigData *ip_data; - const CList *head; - gs_unref_ptrarray GPtrArray *array_domains = NULL; + NMConfigData *data; + guint i, j; if (priv->config_variant) return priv->config_variant; - global_config = nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)); + data = nm_config_get_data (priv->config); + global_config = nm_config_data_get_global_dns_config (data); if (global_config) { priv->config_variant = _get_global_config_variant (global_config); _LOGT ("current configuration: %s", (str = g_variant_print (priv->config_variant, TRUE))); @@ -1922,26 +1826,25 @@ _get_config_variant (NMDnsManager *self) g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); - head = _ip_config_lst_head (self); - c_list_for_each_entry (ip_data, head, ip_config_lst) { - const NMIPConfig *ip_config = ip_data->ip_config; + for (i = 0; i < priv->configs->len; i++) { + NMDnsIPConfigData *current = priv->configs->pdata[i]; + const NMIPConfig *config = current->config; GVariantBuilder entry_builder; GVariantBuilder strv_builder; - guint i, num; - const int addr_family = nm_ip_config_get_addr_family (ip_config); + guint num; + const int addr_family = nm_ip_config_get_addr_family (config); char buf[NM_UTILS_INET_ADDRSTRLEN]; const NMIPAddr *addr; - const char *ifname; - num = nm_ip_config_get_num_nameservers (ip_config); + num = nm_ip_config_get_num_nameservers (config); if (!num) continue; g_variant_builder_init (&entry_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_init (&strv_builder, G_VARIANT_TYPE ("as")); - for (i = 0; i < num; i++) { - addr = nm_ip_config_get_nameserver (ip_config, i); + for (j = 0; j < num; j++) { + addr = nm_ip_config_get_nameserver (config, j); g_variant_builder_add (&strv_builder, "s", nm_utils_inet_ntop (addr_family, addr, buf)); @@ -1951,47 +1854,36 @@ _get_config_variant (NMDnsManager *self) "nameservers", g_variant_builder_end (&strv_builder)); - - num = nm_ip_config_get_num_domains (ip_config); - num += nm_ip_config_get_num_searches (ip_config); + num = nm_ip_config_get_num_domains (config); if (num > 0) { - if (!array_domains) - array_domains = g_ptr_array_sized_new (num); - else - g_ptr_array_set_size (array_domains, 0); - - add_dns_domains (array_domains, ip_config, TRUE, FALSE); - if (array_domains->len) { - g_variant_builder_init (&strv_builder, G_VARIANT_TYPE ("as")); - for (i = 0; i < array_domains->len; i++) { - g_variant_builder_add (&strv_builder, - "s", - array_domains->pdata[i]); - } - g_variant_builder_add (&entry_builder, - "{sv}", - "domains", - g_variant_builder_end (&strv_builder)); + g_variant_builder_init (&strv_builder, G_VARIANT_TYPE ("as")); + for (j = 0; j < num; j++) { + g_variant_builder_add (&strv_builder, + "s", + nm_ip_config_get_domain (config, j)); } + g_variant_builder_add (&entry_builder, + "{sv}", + "domains", + g_variant_builder_end (&strv_builder)); } - ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ip_data->data->ifindex); - if (ifname) { + if (current->iface) { g_variant_builder_add (&entry_builder, "{sv}", "interface", - g_variant_new_string (ifname)); + g_variant_new_string (current->iface)); } g_variant_builder_add (&entry_builder, "{sv}", "priority", - g_variant_new_int32 (nm_ip_config_get_dns_priority (ip_config))); + g_variant_new_int32 (nm_ip_config_get_dns_priority (config))); g_variant_builder_add (&entry_builder, "{sv}", "vpn", - g_variant_new_boolean (ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN)); + g_variant_new_boolean (current->type == NM_DNS_IP_CONFIG_TYPE_VPN)); g_variant_builder_add (&builder, "a{sv}", &entry_builder); } @@ -2032,12 +1924,8 @@ nm_dns_manager_init (NMDnsManager *self) _LOGT ("creating..."); - c_list_init (&priv->ip_config_lst_head); - priv->config = g_object_ref (nm_config_get ()); - - priv->configs = g_hash_table_new_full (nm_direct_hash, NULL, - NULL, (GDestroyNotify) _config_data_free); + priv->configs = g_ptr_array_new_full (8, ip_config_data_destroy); /* Set the initial hash */ compute_hash (self, NULL, NM_DNS_MANAGER_GET_PRIVATE (self)->hash); @@ -2054,33 +1942,33 @@ dispose (GObject *object) { NMDnsManager *self = NM_DNS_MANAGER (object); NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - NMDnsIPConfigData *ip_data, *ip_data_safe; + NMDnsIPConfigData *data; + guint i; _LOGT ("disposing"); if (!priv->is_stopped) nm_dns_manager_stop (self); - if (priv->config) - g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self); - _clear_plugin (self); - priv->best_ip_config_4 = NULL; - priv->best_ip_config_6 = NULL; - - c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_config_lst_head, ip_config_lst) - _ip_config_data_free (ip_data); + if (priv->config) { + g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self); + g_clear_object (&priv->config); + } - g_clear_pointer (&priv->configs, g_hash_table_destroy); + if (priv->configs) { + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + forget_data (self, data); + } + g_ptr_array_free (priv->configs, TRUE); + priv->configs = NULL; + } nm_clear_g_source (&priv->plugin_ratelimit.timer); - g_clear_object (&priv->config); - G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); - - g_clear_pointer (&priv->config_variant, g_variant_unref); } static void @@ -2095,30 +1983,18 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_dns_manager_parent_class)->finalize (object); } -static const NMDBusInterfaceInfoExtended interface_info_dns_manager = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DNS_MANAGER, - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mode", "s", NM_DNS_MANAGER_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("RcManager", "s", NM_DNS_MANAGER_RC_MANAGER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Configuration", "aa{sv}", NM_DNS_MANAGER_CONFIGURATION), - ), - ), -}; - static void nm_dns_manager_class_init (NMDnsManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (klass); object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; - dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_STATIC (NM_DBUS_PATH "/DnsManager"); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_dns_manager); - dbus_object_class->export_on_construction = TRUE; + exported_object_class->export_path = NM_DBUS_PATH "/DnsManager"; + exported_object_class->export_on_construction = TRUE; obj_properties[PROP_MODE] = g_param_spec_string (NM_DNS_MANAGER_MODE, "", "", @@ -2148,4 +2024,9 @@ nm_dns_manager_class_init (NMDnsManagerClass *klass) 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DNS_MANAGER_SKELETON, + NULL); } + diff --git a/src/dns/nm-dns-manager.h b/src/dns/nm-dns-manager.h index 56889367..b38ea701 100644 --- a/src/dns/nm-dns-manager.h +++ b/src/dns/nm-dns-manager.h @@ -26,14 +26,11 @@ #include "nm-ip4-config.h" #include "nm-ip6-config.h" -#include "nm-setting-connection.h" typedef enum { - NM_DNS_IP_CONFIG_TYPE_REMOVED = -1, - NM_DNS_IP_CONFIG_TYPE_DEFAULT = 0, NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, - NM_DNS_IP_CONFIG_TYPE_VPN, + NM_DNS_IP_CONFIG_TYPE_VPN } NMDnsIPConfigType; enum { @@ -41,23 +38,12 @@ enum { NM_DNS_PRIORITY_DEFAULT_VPN = 50, }; -struct _NMDnsConfigData; -struct _NMDnsManager; - typedef struct { - struct _NMDnsConfigData *data; - NMIPConfig *ip_config; - CList data_lst; - CList ip_config_lst; - NMDnsIPConfigType ip_config_type; + gpointer config; + NMDnsIPConfigType type; + char *iface; } NMDnsIPConfigData; -typedef struct _NMDnsConfigData { - struct _NMDnsManager *self; - CList data_lst_head; - int ifindex; -} NMDnsConfigData; - #define NM_TYPE_DNS_MANAGER (nm_dns_manager_get_type ()) #define NM_DNS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NM_TYPE_DNS_MANAGER, NMDnsManager)) #define NM_DNS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NM_TYPE_DNS_MANAGER, NMDnsManagerClass)) @@ -84,9 +70,12 @@ NMDnsManager * nm_dns_manager_get (void); void nm_dns_manager_begin_updates (NMDnsManager *self, const char *func); void nm_dns_manager_end_updates (NMDnsManager *self, const char *func); -gboolean nm_dns_manager_set_ip_config (NMDnsManager *self, - NMIPConfig *ip_config, - NMDnsIPConfigType ip_config_type); +gboolean nm_dns_manager_add_ip_config (NMDnsManager *self, + const char *iface, + gpointer config, + NMDnsIPConfigType cfg_type); + +gboolean nm_dns_manager_remove_ip_config (NMDnsManager *self, gpointer config); void nm_dns_manager_set_initial_hostname (NMDnsManager *self, const char *hostname); @@ -123,6 +112,8 @@ typedef enum { NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, } NMDnsManagerResolvConfManager; +gboolean nm_dns_manager_get_resolv_conf_explicit (NMDnsManager *self); + void nm_dns_manager_stop (NMDnsManager *self); #endif /* __NETWORKMANAGER_DNS_MANAGER_H__ */ diff --git a/src/dns/nm-dns-plugin.c b/src/dns/nm-dns-plugin.c index d9400e3e..5805b7d8 100644 --- a/src/dns/nm-dns-plugin.c +++ b/src/dns/nm-dns-plugin.c @@ -77,15 +77,15 @@ G_DEFINE_TYPE_EXTENDED (NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT, G_TYPE_FLAG_A gboolean nm_dns_plugin_update (NMDnsPlugin *self, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, - const CList *ip_config_lst_head, const char *hostname) { g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE); return NM_DNS_PLUGIN_GET_CLASS (self)->update (self, + configs, global_config, - ip_config_lst_head, hostname); } diff --git a/src/dns/nm-dns-plugin.h b/src/dns/nm-dns-plugin.h index 80b77d95..996695c0 100644 --- a/src/dns/nm-dns-plugin.h +++ b/src/dns/nm-dns-plugin.h @@ -50,8 +50,8 @@ typedef struct { * configuration. */ gboolean (*update) (NMDnsPlugin *self, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, - const CList *ip_config_lst_head, const char *hostname); /* Subclasses should override and return TRUE if they start a local @@ -80,8 +80,8 @@ gboolean nm_dns_plugin_is_caching (NMDnsPlugin *self); const char *nm_dns_plugin_get_name (NMDnsPlugin *self); gboolean nm_dns_plugin_update (NMDnsPlugin *self, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, - const CList *ip_config_lst_head, const char *hostname); void nm_dns_plugin_stop (NMDnsPlugin *self); 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); } diff --git a/src/dns/nm-dns-unbound.c b/src/dns/nm-dns-unbound.c index e06128aa..0b80055f 100644 --- a/src/dns/nm-dns-unbound.c +++ b/src/dns/nm-dns-unbound.c @@ -39,8 +39,8 @@ G_DEFINE_TYPE (NMDnsUnbound, nm_dns_unbound, NM_TYPE_DNS_PLUGIN) static gboolean update (NMDnsPlugin *plugin, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, - const CList *ip_config_lst_head, const char *hostname) { char *argv[] = { DNSSEC_TRIGGER_SCRIPT, "--async", "--update", NULL }; |