diff options
Diffstat (limited to 'src/core/dns/nm-dns-manager.c')
-rw-r--r-- | src/core/dns/nm-dns-manager.c | 594 |
1 files changed, 317 insertions, 277 deletions
diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index f0ec0c8921..1ca33e46ac 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -7,6 +7,8 @@ #include "src/core/nm-default-daemon.h" +#include "nm-dns-manager.h" + #include <fcntl.h> #include <resolv.h> #include <stdlib.h> @@ -22,22 +24,20 @@ #include <libpsl.h> #endif -#include "libnm-glib-aux/nm-str-buf.h" -#include "nm-utils.h" #include "libnm-core-intern/nm-core-internal.h" -#include "nm-dns-manager.h" -#include "nm-ip4-config.h" -#include "nm-ip6-config.h" +#include "libnm-glib-aux/nm-str-buf.h" + #include "NetworkManagerUtils.h" +#include "devices/nm-device.h" #include "nm-config.h" #include "nm-dbus-object.h" -#include "devices/nm-device.h" -#include "nm-manager.h" - -#include "nm-dns-plugin.h" #include "nm-dns-dnsmasq.h" +#include "nm-dns-plugin.h" #include "nm-dns-systemd-resolved.h" #include "nm-dns-unbound.h" +#include "nm-l3-config-data.h" +#include "nm-manager.h" +#include "nm-utils.h" #define HASH_LEN NM_UTILS_CHECKSUM_LENGTH_SHA1 @@ -84,22 +84,21 @@ typedef struct { GHashTable *configs_dict; CList configs_lst_head; - CList ip_config_lst_head; + CList ip_data_lst_head; GVariant *config_variant; - bool ip_config_lst_need_sort : 1; + bool ip_data_lst_need_sort : 1; bool configs_lst_need_sort : 1; bool dns_touched : 1; bool is_stopped : 1; + bool config_changed : 1; + char *hostname; guint updates_queue; - guint8 hash[HASH_LEN]; /* SHA1 hash of current DNS config */ - guint8 prev_hash[HASH_LEN]; /* Hash when begin_updates() was called */ - NMDnsManagerResolvConfManager rc_manager; char * mode; NMDnsPlugin * sd_resolve_plugin; @@ -159,11 +158,6 @@ NM_DEFINE_SINGLETON_GETTER(NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER /*****************************************************************************/ -static void -_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data); - -/*****************************************************************************/ - static gboolean domain_is_valid(const char *domain, gboolean check_public_suffix) { @@ -208,6 +202,24 @@ static NM_UTILS_LOOKUP_STR_DEFINE( /*****************************************************************************/ +static int +_dns_config_ip_data_get_dns_priority1(const NML3ConfigData *l3cd, int addr_family) +{ + int prio; + + if (!nm_l3_config_data_get_dns_priority(l3cd, addr_family, &prio)) + return 0; + + nm_assert(prio != 0); + return prio; +} + +static int +_dns_config_ip_data_get_dns_priority(const NMDnsConfigIPData *ip_data) +{ + return _dns_config_ip_data_get_dns_priority1(ip_data->l3cd, ip_data->addr_family); +} + static void _ASSERT_dns_config_data(const NMDnsConfigData *data) { @@ -221,9 +233,9 @@ _ASSERT_dns_config_ip_data(const NMDnsConfigIPData *ip_data) { nm_assert(ip_data); _ASSERT_dns_config_data(ip_data->data); - nm_assert(NM_IS_IP_CONFIG(ip_data->ip_config)); + nm_assert(NM_IS_L3_CONFIG_DATA(ip_data->l3cd)); 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)); + nm_assert(ip_data->data->ifindex == nm_l3_config_data_get_ifindex(ip_data->l3cd)); #if NM_MORE_ASSERTS > 5 { gboolean has_default = FALSE; @@ -243,37 +255,36 @@ _ASSERT_dns_config_ip_data(const NMDnsConfigIPData *ip_data) if (ip_data->domains.has_default_route_exclusive) nm_assert(ip_data->domains.has_default_route); } + nm_assert(_dns_config_ip_data_get_dns_priority(ip_data) != 0); #endif } static NMDnsConfigIPData * -_dns_config_ip_data_new(NMDnsConfigData * data, - NMIPConfig * ip_config, - NMDnsIPConfigType ip_config_type) +_dns_config_ip_data_new(NMDnsConfigData * data, + int addr_family, + gconstpointer source_tag, + const NML3ConfigData *l3cd, + NMDnsIPConfigType ip_config_type) { NMDnsConfigIPData *ip_data; _ASSERT_dns_config_data(data); - nm_assert(NM_IS_IP_CONFIG(ip_config)); + nm_assert(NM_IS_L3_CONFIG_DATA(l3cd)); nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED); ip_data = g_slice_new(NMDnsConfigIPData); *ip_data = (NMDnsConfigIPData){ .data = data, - .ip_config = g_object_ref(ip_config), + .source_tag = source_tag, + .l3cd = nm_l3_config_data_ref_and_seal(l3cd), .ip_config_type = ip_config_type, + .addr_family = addr_family, }; 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); - - /* We also need to set priv->ip_config_lst_need_sort, but the caller will do that! */ + c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_data_lst_head, + &ip_data->ip_data_lst); - g_signal_connect(ip_config, - NM_IS_IP4_CONFIG(ip_config) ? "notify::" NM_IP4_CONFIG_DNS_PRIORITY - : "notify::" NM_IP6_CONFIG_DNS_PRIORITY, - G_CALLBACK(_ip_config_dns_priority_changed), - ip_data); + /* We also need to set priv->ip_data_lst_need_sort, but the caller will do that! */ _ASSERT_dns_config_ip_data(ip_data); return ip_data; @@ -285,35 +296,15 @@ _dns_config_ip_data_free(NMDnsConfigIPData *ip_data) _ASSERT_dns_config_ip_data(ip_data); c_list_unlink_stale(&ip_data->data_lst); - c_list_unlink_stale(&ip_data->ip_config_lst); + c_list_unlink_stale(&ip_data->ip_data_lst); g_free(ip_data->domains.search); g_strfreev(ip_data->domains.reverse); - g_signal_handlers_disconnect_by_func(ip_data->ip_config, - _ip_config_dns_priority_changed, - ip_data); - - g_object_unref(ip_data->ip_config); + nm_l3_config_data_unref(ip_data->l3cd); nm_g_slice_free(ip_data); } -static NMDnsConfigIPData * -_dns_config_data_find_ip_config(NMDnsConfigData *data, NMIPConfig *ip_config) -{ - NMDnsConfigIPData *ip_data; - - _ASSERT_dns_config_data(data); - - c_list_for_each_entry (ip_data, &data->data_lst_head, data_lst) { - _ASSERT_dns_config_ip_data(ip_data); - - if (ip_data->ip_config == ip_config) - return ip_data; - } - return NULL; -} - static void _dns_config_data_free(NMDnsConfigData *data) { @@ -325,14 +316,13 @@ _dns_config_data_free(NMDnsConfigData *data) } static int -_mgr_get_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data) +_mgr_get_ip_data_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data) { - const NMDnsConfigIPData *a = c_list_entry(a_lst, NMDnsConfigIPData, ip_config_lst); - const NMDnsConfigIPData *b = c_list_entry(b_lst, NMDnsConfigIPData, ip_config_lst); + const NMDnsConfigIPData *a = c_list_entry(a_lst, NMDnsConfigIPData, ip_data_lst); + const NMDnsConfigIPData *b = c_list_entry(b_lst, NMDnsConfigIPData, ip_data_lst); /* Configurations with lower priority value first */ - NM_CMP_DIRECT(nm_ip_config_get_dns_priority(a->ip_config), - nm_ip_config_get_dns_priority(b->ip_config)); + NM_CMP_DIRECT(_dns_config_ip_data_get_dns_priority(a), _dns_config_ip_data_get_dns_priority(b)); /* Sort according to type (descendingly) */ NM_CMP_FIELD(b, a, ip_config_type); @@ -341,16 +331,16 @@ _mgr_get_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *u } static CList * -_mgr_get_ip_config_lst_head(NMDnsManager *self) +_mgr_get_ip_data_lst_head(NMDnsManager *self) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); - if (G_UNLIKELY(priv->ip_config_lst_need_sort)) { - priv->ip_config_lst_need_sort = FALSE; - c_list_sort(&priv->ip_config_lst_head, _mgr_get_ip_config_lst_cmp, NULL); + if (G_UNLIKELY(priv->ip_data_lst_need_sort)) { + priv->ip_data_lst_need_sort = FALSE; + c_list_sort(&priv->ip_data_lst_head, _mgr_get_ip_data_lst_cmp, NULL); } - return &priv->ip_config_lst_head; + return &priv->ip_data_lst_head; } static int @@ -430,28 +420,33 @@ 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) +add_dns_domains(GPtrArray * array, + int addr_family, + const NML3ConfigData *l3cd, + gboolean include_routing, + gboolean dup) { - guint num_domains, num_searches, i; - const char *str; + const char *const *domains; + const char *const *searches; + guint num_domains; + guint num_searches; + guint i; + const char * str; - num_domains = nm_ip_config_get_num_domains(ip_config); - num_searches = nm_ip_config_get_num_searches(ip_config); + domains = nm_l3_config_data_get_domains(l3cd, addr_family, &num_domains); + searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches); for (i = 0; i < num_searches; i++) { - str = nm_ip_config_get_search(ip_config, i); + str = searches[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) { + if (num_domains > 1 || num_searches == 0) { for (i = 0; i < num_domains; i++) { - str = nm_ip_config_get_domain(ip_config, i); + str = domains[i]; if (!include_routing && domain_is_routing(str)) continue; if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE)) @@ -462,26 +457,24 @@ add_dns_domains(GPtrArray * array, } static void -merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_config) +merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3ConfigData *l3cd) { - int addr_family; - char buf[NM_UTILS_INET_ADDRSTRLEN + 50]; - gboolean has_trust_ad; - guint num_nameservers; - guint num; - guint i; - - addr_family = nm_ip_config_get_addr_family(ip_config); + char buf[NM_UTILS_INET_ADDRSTRLEN + 50]; + gboolean has_trust_ad; + guint num_nameservers; + guint num; + guint i; + gconstpointer nameservers; + const char *const *strv; - nm_assert_addr_family(addr_family); - nm_assert(ifindex > 0); - nm_assert(ifindex == nm_ip_config_get_ifindex(ip_config)); + nm_assert(ifindex == nm_l3_config_data_get_ifindex(l3cd)); - num_nameservers = nm_ip_config_get_num_nameservers(ip_config); + nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); for (i = 0; i < num_nameservers; i++) { const NMIPAddr *addr; - addr = nm_ip_config_get_nameserver(ip_config, i); + addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i); + if (addr_family == AF_INET) nm_utils_inet_ntop(addr_family, addr, buf); else if (IN6_IS_ADDR_V4MAPPED(addr)) @@ -502,22 +495,23 @@ merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_conf add_string_item(rc->nameservers, buf, TRUE); } - add_dns_domains(rc->searches, ip_config, FALSE, TRUE); + add_dns_domains(rc->searches, addr_family, l3cd, FALSE, TRUE); has_trust_ad = FALSE; - num = nm_ip_config_get_num_dns_options(ip_config); + strv = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num); for (i = 0; i < num; i++) { - const char *option = nm_ip_config_get_dns_option(ip_config, i); + const char *option = strv[i]; if (nm_streq(option, NM_SETTING_DNS_OPTION_TRUST_AD)) { has_trust_ad = TRUE; continue; } - add_dns_option_item(rc->options, nm_ip_config_get_dns_option(ip_config, i)); + add_dns_option_item(rc->options, option); } + if (num_nameservers == 0) { - /* If the @ip_config contributes no DNS servers, ignore whether trust-ad is set or unset - * for this @ip_config. */ + /* If the @l3cd contributes no DNS servers, ignore whether trust-ad is set or unset + * for this @l3cd. */ } else if (has_trust_ad) { /* We only set has_trust_ad to TRUE, if all IP configs agree (or don't contribute). * Once set to FALSE, it doesn't get reset. */ @@ -527,20 +521,17 @@ merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_conf rc->has_trust_ad = NM_TERNARY_FALSE; if (addr_family == AF_INET) { - const NMIP4Config *ip4_config = (const NMIP4Config *) ip_config; + const in_addr_t *nis_servers; + const char * nis_domain; - /* NIS stuff */ - num = nm_ip4_config_get_num_nis_servers(ip4_config); - 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); - } + nis_servers = nm_l3_config_data_get_nis_servers(l3cd, &num); + for (i = 0; i < num; i++) + add_string_item(rc->nis_servers, _nm_utils_inet4_ntop(nis_servers[i], buf), TRUE); - if (nm_ip4_config_get_nis_domain(ip4_config)) { + if ((nis_domain = nm_l3_config_data_get_nis_domain(l3cd))) { /* FIXME: handle multiple domains */ if (!rc->nis_domain) - rc->nis_domain = nm_ip4_config_get_nis_domain(ip4_config); + rc->nis_domain = nis_domain; } } } @@ -1106,30 +1097,6 @@ update_resolv_conf(NMDnsManager * self, return write_file_result; } -static void -compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[static HASH_LEN]) -{ - nm_auto_free_checksum GChecksum *sum = NULL; - NMDnsConfigIPData * ip_data; - - sum = g_checksum_new(G_CHECKSUM_SHA1); - nm_assert(HASH_LEN == g_checksum_type_get_length(G_CHECKSUM_SHA1)); - - if (global) - nm_global_dns_config_update_checksum(global, sum); - else { - const CList *head; - - /* FIXME(ip-config-checksum): this relies on the fact that an IP - * configuration without DNS parameters gives a zero checksum. */ - head = _mgr_get_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); - } - - nm_utils_checksum_get_digest_len(sum, buffer, HASH_LEN); -} - static gboolean merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) { @@ -1172,19 +1139,21 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) } static const char * -get_nameserver_list(const NMIPConfig *config, NMStrBuf *tmp_strbuf) +get_nameserver_list(int addr_family, const NML3ConfigData *l3cd, NMStrBuf *tmp_strbuf) { - char buf[NM_UTILS_INET_ADDRSTRLEN]; - int addr_family; - guint num; - guint i; + char buf[NM_UTILS_INET_ADDRSTRLEN]; + guint num; + guint i; + gconstpointer nameservers; nm_str_buf_reset(tmp_strbuf); - addr_family = nm_ip_config_get_addr_family(config); - num = nm_ip_config_get_num_nameservers(config); + nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num); for (i = 0; i < num; i++) { - nm_utils_inet_ntop(addr_family, nm_ip_config_get_nameserver(config, i), buf); + const NMIPAddr *addr; + + addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i); + nm_utils_inet_ntop(addr_family, addr->addr_ptr, buf); if (i > 0) nm_str_buf_append_c(tmp_strbuf, ' '); nm_str_buf_append(tmp_strbuf, buf); @@ -1227,36 +1196,39 @@ _collect_resolv_conf_data(NMDnsManager * self, merge_global_dns_config(&rc, global_config); else { nm_auto_str_buf NMStrBuf tmp_strbuf = NM_STR_BUF_INIT(0, FALSE); - int prio; int first_prio = 0; const NMDnsConfigIPData *ip_data; const CList * head; gboolean is_first = TRUE; - head = _mgr_get_ip_config_lst_head(self); - c_list_for_each_entry (ip_data, head, ip_config_lst) { + head = _mgr_get_ip_data_lst_head(self); + c_list_for_each_entry (ip_data, head, ip_data_lst) { gboolean skip = FALSE; + int dns_priority; _ASSERT_dns_config_ip_data(ip_data); - prio = nm_ip_config_get_dns_priority(ip_data->ip_config); + if (!nm_l3_config_data_get_dns_priority(ip_data->l3cd, + ip_data->addr_family, + &dns_priority)) + nm_assert_not_reached(); if (is_first) { is_first = FALSE; - first_prio = prio; - } else if (first_prio < 0 && first_prio != prio) + first_prio = dns_priority; + } else if (first_prio < 0 && first_prio != dns_priority) skip = TRUE; _LOGT("config: %8d %-7s v%c %-5d %s: %s", - prio, + dns_priority, _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)), + nm_utils_addr_family_to_char(ip_data->addr_family), ip_data->data->ifindex, skip ? "<SKIP>" : "", - get_nameserver_list(ip_data->ip_config, &tmp_strbuf)); + get_nameserver_list(ip_data->addr_family, ip_data->l3cd, &tmp_strbuf)); if (!skip) - merge_one_ip_config(&rc, ip_data->data->ifindex, ip_data->ip_config); + merge_one_l3cd(&rc, ip_data->addr_family, ip_data->data->ifindex, ip_data->l3cd); } } @@ -1292,27 +1264,32 @@ _collect_resolv_conf_data(NMDnsManager * self, /*****************************************************************************/ static char ** -get_ip_rdns_domains(NMIPConfig *ip_config) +get_ip_rdns_domains(int addr_family, const NML3ConfigData *l3cd) { - int addr_family = nm_ip_config_get_addr_family(ip_config); - char ** strv; - GPtrArray * domains; - NMDedupMultiIter ipconf_iter; - const NMPlatformIPAddress *address; - const NMPlatformIPRoute * route; - - nm_assert_addr_family(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + char ** strv; + GPtrArray * domains; + NMDedupMultiIter ipconf_iter; + const NMPObject *obj; domains = g_ptr_array_sized_new(5); - nm_ip_config_iter_ip_address_for_each (&ipconf_iter, ip_config, &address) { + nm_l3_config_data_iter_obj_for_each (&ipconf_iter, + l3cd, + &obj, + NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { nm_utils_get_reverse_dns_domains_ip(addr_family, - address->address_ptr, - address->plen, + NMP_OBJECT_CAST_IP_ADDRESS(obj)->address_ptr, + NMP_OBJECT_CAST_IP_ADDRESS(obj)->plen, domains); } - nm_ip_config_iter_ip_route_for_each (&ipconf_iter, ip_config, &route) { + nm_l3_config_data_iter_obj_for_each (&ipconf_iter, + l3cd, + &obj, + NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { + const NMPlatformIPRoute *route = NMP_OBJECT_CAST_IP_ROUTE(obj); + if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) { nm_utils_get_reverse_dns_domains_ip(addr_family, route->network_ptr, @@ -1394,12 +1371,12 @@ _mgr_configs_data_construct(NMDnsManager *self) CList * head; int prev_priority = G_MININT; - head = _mgr_get_ip_config_lst_head(self); + head = _mgr_get_ip_data_lst_head(self); #if NM_MORE_ASSERTS /* we call _mgr_configs_data_clear() at the end of update. We * don't expect any domain settings here. */ - c_list_for_each_entry (ip_data, head, ip_config_lst) { + c_list_for_each_entry (ip_data, head, ip_data_lst) { nm_assert(!ip_data->domains.search); nm_assert(!ip_data->domains.reverse); nm_assert(!ip_data->domains.has_default_route_explicit); @@ -1408,15 +1385,17 @@ _mgr_configs_data_construct(NMDnsManager *self) } #endif - c_list_for_each_entry (ip_data, head, ip_config_lst) { - NMIPConfig *ip_config = ip_data->ip_config; - gboolean add_wildcard = FALSE; + c_list_for_each_entry (ip_data, head, ip_data_lst) { + gboolean add_wildcard = FALSE; + guint num; - if (!nm_ip_config_get_num_nameservers(ip_config)) + nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); + if (num == 0) continue; - if (nm_ip_config_best_default_route_get(ip_config)) + if (nm_l3_config_data_get_best_default_route(ip_data->l3cd, ip_data->addr_family)) { + /* FIXME(l3cfg): the best-default route of a l3cd is not significant! */ add_wildcard = TRUE; - else { + } else { /* If a VPN has never-default=no but doesn't get a default * route (this can happen for example when the server * pushes routes with openconnect), and there are no @@ -1424,9 +1403,10 @@ _mgr_configs_data_construct(NMDnsManager *self) * by the server would be unused. It is preferable in this * case to use the VPN DNS server for all queries. */ if (ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN - && !nm_ip_config_get_never_default(ip_data->ip_config) - && nm_ip_config_get_num_searches(ip_data->ip_config) == 0 - && nm_ip_config_get_num_domains(ip_data->ip_config) == 0) + && nm_l3_config_data_get_never_default(ip_data->l3cd, ip_data->addr_family) + == NM_TERNARY_FALSE + && !nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, NULL) + && !nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, NULL)) add_wildcard = TRUE; } @@ -1437,29 +1417,33 @@ _mgr_configs_data_construct(NMDnsManager *self) } } - c_list_for_each_entry (ip_data, head, ip_config_lst) { - NMIPConfig * ip_config = ip_data->ip_config; - int priority; - const char **domains; - guint n_searches; - guint n_domains; - guint num_dom1; - guint num_dom2; - guint n_domains_allocated; - guint i; - gboolean has_default_route_maybe = FALSE; - gboolean has_default_route_explicit = FALSE; - gboolean has_default_route_auto = FALSE; - - if (!nm_ip_config_get_num_nameservers(ip_config)) + c_list_for_each_entry (ip_data, head, ip_data_lst) { + int priority; + const char ** domains; + const char *const *strv_searches; + const char *const *strv_domains; + guint n_searches; + guint n_domains; + guint num_dom1; + guint num_dom2; + guint n_domains_allocated; + guint i; + gboolean has_default_route_maybe = FALSE; + gboolean has_default_route_explicit = FALSE; + gboolean has_default_route_auto = FALSE; + guint num; + + nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); + if (num == 0) continue; - n_searches = nm_ip_config_get_num_searches(ip_config); - n_domains = nm_ip_config_get_num_domains(ip_config); + strv_searches = + nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, &n_searches); + strv_domains = + nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, &n_domains); - priority = nm_ip_config_get_dns_priority(ip_config); + priority = _dns_config_ip_data_get_dns_priority(ip_data); - nm_assert(priority != 0); nm_assert(prev_priority <= priority); prev_priority = priority; @@ -1487,10 +1471,10 @@ _mgr_configs_data_construct(NMDnsManager *self) /* searches are preferred over domains */ if (n_searches > 0) { for (i = 0; i < n_searches; i++) - domains[num_dom1++] = nm_ip_config_get_search(ip_config, i); + domains[num_dom1++] = strv_searches[i]; } else { for (i = 0; i < n_domains; i++) - domains[num_dom1++] = nm_ip_config_get_domain(ip_config, i); + domains[num_dom1++] = strv_domains[i]; } nm_assert(num_dom1 < n_domains_allocated); @@ -1578,8 +1562,8 @@ _mgr_configs_data_construct(NMDnsManager *self) nm_assert(!ip_data->domains.search); nm_assert(!ip_data->domains.reverse); - ip_data->domains.search = domains; - ip_data->domains.reverse = get_ip_rdns_domains(ip_config); + ip_data->domains.search = domains; + ip_data->domains.reverse = get_ip_rdns_domains(ip_data->addr_family, ip_data->l3cd); ip_data->domains.has_default_route_explicit = has_default_route_explicit; ip_data->domains.has_default_route_exclusive = has_default_route_explicit || (priority < 0 && has_default_route_auto); @@ -1611,8 +1595,8 @@ _mgr_configs_data_clear(NMDnsManager *self) NMDnsConfigIPData *ip_data; CList * head; - head = _mgr_get_ip_config_lst_head(self); - c_list_for_each_entry (ip_data, head, ip_config_lst) { + head = _mgr_get_ip_data_lst_head(self); + c_list_for_each_entry (ip_data, head, ip_data_lst) { nm_clear_g_free(&ip_data->domains.search); nm_clear_pointer(&ip_data->domains.reverse, g_strfreev); ip_data->domains.has_default_route_explicit = FALSE; @@ -1643,6 +1627,8 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError nm_assert(!error || !*error); + priv->config_changed = FALSE; + if (priv->is_stopped) { _LOGD("update-dns: not updating resolv.conf (is stopped)"); return TRUE; @@ -1663,9 +1649,6 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError data = nm_config_get_data(priv->config); global_config = nm_config_data_get_global_dns_config(data); - /* Update hash with config we're applying */ - compute_hash(self, global_config, priv->hash); - _collect_resolv_conf_data(self, global_config, &searches, @@ -1680,7 +1663,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError if (priv->sd_resolve_plugin) { nm_dns_plugin_update(priv->sd_resolve_plugin, global_config, - _mgr_get_ip_config_lst_head(self), + _mgr_get_ip_data_lst_head(self), priv->hostname, NULL); } @@ -1702,7 +1685,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError _LOGD("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update(plugin, global_config, - _mgr_get_ip_config_lst_head(self), + _mgr_get_ip_data_lst_head(self), priv->hostname, &plugin_error)) { _LOGW("update-dns: plugin %s update failed: %s", plugin_name, plugin_error->message); @@ -1834,53 +1817,101 @@ plugin_skip:; /*****************************************************************************/ -static void -_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data) -{ - _ASSERT_dns_config_ip_data(ip_data); - - NM_DNS_MANAGER_GET_PRIVATE(ip_data->data->self)->ip_config_lst_need_sort = TRUE; -} - gboolean -nm_dns_manager_set_ip_config(NMDnsManager * self, - NMIPConfig * ip_config, - NMDnsIPConfigType ip_config_type) +nm_dns_manager_set_ip_config(NMDnsManager * self, + int addr_family, + gconstpointer source_tag, + const NML3ConfigData *l3cd, + NMDnsIPConfigType ip_config_type, + gboolean replace_all) { NMDnsManagerPrivate *priv; - NMDnsConfigIPData * ip_data; NMDnsConfigData * data; int ifindex; + gboolean changed = FALSE; + NMDnsConfigIPData * ip_data = NULL; + int dns_priority; g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE); - g_return_val_if_fail(NM_IS_IP_CONFIG(ip_config), FALSE); + g_return_val_if_fail(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd), FALSE); + g_return_val_if_fail(source_tag, FALSE); + + if (addr_family == AF_UNSPEC) { + /* Setting AF_UNSPEC is a shortcut for calling this function twice for AF_INET and + * AF_INET6. */ + if (nm_dns_manager_set_ip_config(self, + AF_INET, + source_tag, + l3cd, + ip_config_type, + replace_all)) + changed = TRUE; + if (nm_dns_manager_set_ip_config(self, + AF_INET6, + source_tag, + l3cd, + ip_config_type, + replace_all)) + changed = TRUE; + return changed; + } - ifindex = nm_ip_config_get_ifindex(ip_config); - g_return_val_if_fail(ifindex > 0, FALSE); + nm_assert_addr_family(addr_family); priv = NM_DNS_MANAGER_GET_PRIVATE(self); - data = g_hash_table_lookup(priv->configs_dict, &ifindex); - if (!data) - ip_data = NULL; - else - ip_data = _dns_config_data_find_ip_config(data, ip_config); + data = NULL; + if (l3cd) { + ifindex = nm_l3_config_data_get_ifindex(l3cd); + nm_assert(ifindex > 0); + data = g_hash_table_lookup(priv->configs_dict, &ifindex); + } - if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED) { - if (!ip_data) - return FALSE; - /* deleting a config doesn't invalidate the configs' sort order. */ - _dns_config_ip_data_free(ip_data); - if (c_list_is_empty(&data->data_lst_head)) - g_hash_table_remove(priv->configs_dict, &ifindex); - goto changed; + if (data) { + NMDnsConfigIPData *ip_data_iter; + NMDnsConfigIPData *ip_data_safe; + + c_list_for_each_entry_safe (ip_data_iter, ip_data_safe, &data->data_lst_head, data_lst) { + _ASSERT_dns_config_ip_data(ip_data_iter); + + if (ip_data_iter->source_tag != source_tag) + continue; + if (ip_data_iter->addr_family != addr_family) + continue; + + if (ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED && ip_data_iter->l3cd == l3cd) { + nm_assert(!ip_data); + ip_data = ip_data_iter; + continue; + } + + if (!replace_all && l3cd && ip_data_iter->l3cd != l3cd) + continue; + + changed = TRUE; + _dns_config_ip_data_free(ip_data_iter); + } } + if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED) + goto done; + + if (!l3cd) + goto done; + if (ip_data && ip_data->ip_config_type == ip_config_type) { /* nothing to do. */ - return FALSE; + goto done; } + dns_priority = _dns_config_ip_data_get_dns_priority1(l3cd, addr_family); + if (dns_priority == 0) { + /* no DNS priority for this address family. Skip it! */ + goto done; + } + + changed = TRUE; + if (!data) { data = g_slice_new(NMDnsConfigData); *data = (NMDnsConfigData){ @@ -1895,13 +1926,28 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, } if (!ip_data) - ip_data = _dns_config_ip_data_new(data, ip_config, ip_config_type); + ip_data = _dns_config_ip_data_new(data, addr_family, source_tag, l3cd, ip_config_type); else ip_data->ip_config_type = ip_config_type; - priv->ip_config_lst_need_sort = TRUE; + priv->ip_data_lst_need_sort = TRUE; + + nm_assert(l3cd); + nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED); + nm_assert(ip_data->addr_family == addr_family); + nm_assert(ip_data->source_tag == source_tag); + nm_assert(ip_data->l3cd == l3cd); + nm_assert(ip_data->ip_config_type == ip_config_type); + +done: + if (!changed) + return FALSE; + + priv->config_changed = TRUE; + + if (data && c_list_is_empty(&data->data_lst_head)) + g_hash_table_remove(priv->configs_dict, data); -changed: if (!priv->updates_queue) { gs_free_error GError *error = NULL; @@ -1957,11 +2003,8 @@ nm_dns_manager_begin_updates(NMDnsManager *self, const char *func) NMDnsManagerPrivate *priv; g_return_if_fail(self != NULL); - priv = NM_DNS_MANAGER_GET_PRIVATE(self); - /* Save current hash when starting a new batch */ - if (priv->updates_queue == 0) - memcpy(priv->prev_hash, priv->hash, sizeof(priv->hash)); + priv = NM_DNS_MANAGER_GET_PRIVATE(self); priv->updates_queue++; @@ -1973,20 +2016,16 @@ nm_dns_manager_end_updates(NMDnsManager *self, const char *func) { NMDnsManagerPrivate *priv; gs_free_error GError *error = NULL; - gboolean changed; - guint8 new[HASH_LEN]; g_return_if_fail(self != NULL); priv = NM_DNS_MANAGER_GET_PRIVATE(self); g_return_if_fail(priv->updates_queue > 0); - 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"); + _LOGD("(%s): DNS configuration %s", func, priv->config_changed ? "changed" : "did not change"); priv->updates_queue--; - if ((priv->updates_queue > 0) || (changed == FALSE)) { + if ((priv->updates_queue > 0) || !priv->config_changed) { _LOGD("(%s): no DNS changes to commit (%d)", func, priv->updates_queue); return; } @@ -1995,8 +2034,6 @@ nm_dns_manager_end_updates(NMDnsManager *self, const char *func) _LOGD("(%s): committing DNS changes (%d)", func, priv->updates_queue); if (!update_dns(self, FALSE, FALSE, &error)) _LOGW("could not commit DNS changes: %s", error->message); - - memset(priv->prev_hash, 0, sizeof(priv->prev_hash)); } void @@ -2319,6 +2356,8 @@ config_changed_cb(NMConfig * config, NMConfigData * old_data, NMDnsManager * self) { + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); + if (NM_FLAGS_ANY(changes, NM_CONFIG_CHANGE_DNS_MODE | NM_CONFIG_CHANGE_RC_MANAGER | NM_CONFIG_CHANGE_CAUSE_SIGHUP | NM_CONFIG_CHANGE_CAUSE_DNS_FULL)) { @@ -2338,6 +2377,7 @@ config_changed_cb(NMConfig * config, | NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) { gs_free_error GError *error = NULL; + priv->config_changed = TRUE; if (!update_dns(self, FALSE, TRUE, &error)) _LOGW("could not commit DNS changes: %s", error->message); } @@ -2415,51 +2455,54 @@ _get_config_variant(NMDnsManager *self) g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - head = _mgr_get_ip_config_lst_head(self); - c_list_for_each_entry (ip_data, head, ip_config_lst) { - const NMIPConfig *ip_config = ip_data->ip_config; - GVariantBuilder entry_builder; - GVariantBuilder strv_builder; - guint i, num; - const int addr_family = nm_ip_config_get_addr_family(ip_config); - char buf[NM_UTILS_INET_ADDRSTRLEN]; - const NMIPAddr * addr; - const char * ifname; - - num = nm_ip_config_get_num_nameservers(ip_config); - if (!num) + head = _mgr_get_ip_data_lst_head(self); + c_list_for_each_entry (ip_data, head, ip_data_lst) { + GVariantBuilder entry_builder; + GVariantBuilder strv_builder; + guint num; + guint num_domains; + guint num_searches; + guint i; + char buf[NM_UTILS_INET_ADDRSTRLEN]; + const char * ifname; + gconstpointer nameservers; + + nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); + if (num == 0) 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); - g_variant_builder_add(&strv_builder, "s", nm_utils_inet_ntop(addr_family, addr, buf)); + const NMIPAddr *addr; + + addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i); + g_variant_builder_add(&strv_builder, + "s", + nm_utils_inet_ntop(ip_data->addr_family, addr, buf)); } g_variant_builder_add(&entry_builder, "{sv}", "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); + nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, &num_domains); + nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, &num_searches); + num = num_domains + num_searches; 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); + add_dns_domains(array_domains, ip_data->addr_family, ip_data->l3cd, 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_new_strv((const char *const *) array_domains->pdata, + array_domains->len)); } } @@ -2474,7 +2517,7 @@ _get_config_variant(NMDnsManager *self) g_variant_builder_add(&entry_builder, "{sv}", "priority", - g_variant_new_int32(nm_ip_config_get_dns_priority(ip_config))); + g_variant_new_int32(_dns_config_ip_data_get_dns_priority(ip_data))); g_variant_builder_add( &entry_builder, @@ -2521,7 +2564,7 @@ nm_dns_manager_init(NMDnsManager *self) _LOGT("creating..."); c_list_init(&priv->configs_lst_head); - c_list_init(&priv->ip_config_lst_head); + c_list_init(&priv->ip_data_lst_head); priv->config = g_object_ref(nm_config_get()); @@ -2531,9 +2574,6 @@ nm_dns_manager_init(NMDnsManager *self) (GDestroyNotify) _dns_config_data_free, NULL); - /* Set the initial hash */ - compute_hash(self, NULL, NM_DNS_MANAGER_GET_PRIVATE(self)->hash); - g_signal_connect(G_OBJECT(priv->config), NM_CONFIG_SIGNAL_CONFIG_CHANGED, G_CALLBACK(config_changed_cb), @@ -2559,7 +2599,7 @@ dispose(GObject *object) g_clear_object(&priv->sd_resolve_plugin); _clear_plugin(self); - c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_config_lst_head, ip_config_lst) + c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_data_lst_head, ip_data_lst) _dns_config_ip_data_free(ip_data); nm_clear_pointer(&priv->configs_dict, g_hash_table_destroy); |