diff options
Diffstat (limited to 'src/core/dns')
| -rw-r--r-- | src/core/dns/nm-dns-dnsmasq.c | 34 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-dnsmasq.h | 3 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-manager.c | 128 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-manager.h | 12 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-plugin.h | 2 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-systemd-resolved.c | 216 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-systemd-resolved.h | 2 |
7 files changed, 243 insertions, 154 deletions
diff --git a/src/core/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c index cc7c03a2..8ae1bb96 100644 --- a/src/core/dns/nm-dns-dnsmasq.c +++ b/src/core/dns/nm-dns-dnsmasq.c @@ -801,13 +801,13 @@ add_dnsmasq_nameserver(NMDnsDnsmasq *self, g_variant_builder_close(servers); } -#define IP_ADDR_TO_STRING_BUFLEN (NM_UTILS_INET_ADDRSTRLEN + 1 + IFNAMSIZ) +#define IP_ADDR_TO_STRING_BUFLEN (NM_INET_ADDRSTRLEN + 1 + IFNAMSIZ) static const char * ip_addr_to_string(int addr_family, gconstpointer addr, const char *iface, char *out_buf) { int n_written; - char buf2[NM_UTILS_INET_ADDRSTRLEN]; + char buf2[NM_INET_ADDRSTRLEN]; const char *separator; nm_assert_addr_family(addr_family); @@ -815,13 +815,13 @@ ip_addr_to_string(int addr_family, gconstpointer addr, const char *iface, char * nm_assert(out_buf); if (addr_family == AF_INET) { - nm_utils_inet_ntop(addr_family, addr, buf2); + nm_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); + nm_inet4_ntop(((const struct in6_addr *) addr)->s6_addr32[3], buf2); else - _nm_utils_inet6_ntop(addr, buf2); + nm_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" @@ -868,22 +868,24 @@ add_global_config(NMDnsDnsmasq *self, static void add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPData *ip_data) { - const char *iface; - const char *domain; - char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN]; - gconstpointer nameservers; - guint num; - guint i; - guint j; + const char *iface; + const char *domain; + char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN]; + const char *const *strarr; + guint num; + guint i; + guint j; iface = nm_platform_link_get_name(NM_PLATFORM_GET, ip_data->data->ifindex); - nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); + strarr = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); for (i = 0; i < num; i++) { - gconstpointer addr; + NMIPAddr a; - addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i); - ip_addr_to_string(ip_data->addr_family, addr, iface, ip_addr_to_string_buf); + if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, NULL)) + continue; + + ip_addr_to_string(ip_data->addr_family, &a, iface, ip_addr_to_string_buf); if (!ip_data->domains.has_default_route_explicit && ip_data->domains.has_default_route) add_dnsmasq_nameserver(self, servers, ip_addr_to_string_buf, NULL); diff --git a/src/core/dns/nm-dns-dnsmasq.h b/src/core/dns/nm-dns-dnsmasq.h index 98761d3d..c2f2a115 100644 --- a/src/core/dns/nm-dns-dnsmasq.h +++ b/src/core/dns/nm-dns-dnsmasq.h @@ -10,7 +10,8 @@ #include "nm-dns-manager.h" #define NM_TYPE_DNS_DNSMASQ (nm_dns_dnsmasq_get_type()) -#define NM_DNS_DNSMASQ(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNS_DNSMASQ, NMDnsDnsmasq)) +#define NM_DNS_DNSMASQ(obj) \ + (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNS_DNSMASQ, NMDnsDnsmasq)) #define NM_DNS_DNSMASQ_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DNS_DNSMASQ, NMDnsDnsmasqClass)) #define NM_IS_DNS_DNSMASQ(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DNS_DNSMASQ)) diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index edb8ce0f..6ee2e816 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -552,29 +552,29 @@ add_dns_domains(GPtrArray *array, static void merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3ConfigData *l3cd) { - char buf[NM_UTILS_INET_ADDRSTRLEN + 50]; + char buf[NM_INET_ADDRSTRLEN + 50]; gboolean has_trust_ad; guint num_nameservers; guint num; guint i; - gconstpointer nameservers; - const char *const *strv; + const char *const *strarr; nm_assert(ifindex == nm_l3_config_data_get_ifindex(l3cd)); - nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); + strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); for (i = 0; i < num_nameservers; i++) { - const NMIPAddr *addr; + NMIPAddr a; - addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i); + if (!nm_utils_dnsname_parse_assert(addr_family, strarr[i], NULL, &a, NULL)) + continue; if (addr_family == AF_INET) - nm_utils_inet_ntop(addr_family, addr, buf); - else if (IN6_IS_ADDR_V4MAPPED(addr)) - _nm_utils_inet4_ntop(addr->addr6.s6_addr32[3], buf); + nm_inet_ntop(addr_family, &a, buf); + else if (IN6_IS_ADDR_V4MAPPED(&a)) + nm_inet4_ntop(a.addr6.s6_addr32[3], buf); else { - _nm_utils_inet6_ntop(&addr->addr6, buf); - if (IN6_IS_ADDR_LINKLOCAL(addr)) { + nm_inet6_ntop(&a.addr6, buf); + if (IN6_IS_ADDR_LINKLOCAL(&a)) { const char *ifname; ifname = nm_platform_link_get_name(NM_PLATFORM_GET, ifindex); @@ -591,9 +591,9 @@ merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3Con add_dns_domains(rc->searches, addr_family, l3cd, FALSE, TRUE); has_trust_ad = FALSE; - strv = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num); + strarr = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num); for (i = 0; i < num; i++) { - const char *option = strv[i]; + const char *option = strarr[i]; if (nm_streq(option, NM_SETTING_DNS_OPTION_TRUST_AD)) { has_trust_ad = TRUE; @@ -619,7 +619,7 @@ merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3Con 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); + add_string_item(rc->nis_servers, nm_inet4_ntop(nis_servers[i], buf), TRUE); if ((nis_domain = nm_l3_config_data_get_nis_domain(l3cd))) { /* FIXME: handle multiple domains */ @@ -1201,14 +1201,19 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[ if (global) nm_global_dns_config_update_checksum(global, sum); - else { + + if (!global || !nm_global_dns_config_lookup_domain(global, "*")) { 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_data_lst_head(self); - c_list_for_each_entry (ip_data, head, ip_data_lst) - nm_ip_config_dns_hash(ip_data->l3cd, sum, ip_data->addr_family); + c_list_for_each_entry (ip_data, head, ip_data_lst) { + nm_l3_config_data_hash_dns(ip_data->l3cd, + sum, + ip_data->addr_family, + ip_data->ip_config_type); + } } nm_utils_checksum_get_digest_len(sum, buffer, HASH_LEN); @@ -1244,13 +1249,15 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) } default_domain = nm_global_dns_config_lookup_domain(global_conf, "*"); - nm_assert(default_domain); + if (!default_domain) + return TRUE; 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); - } + if (!servers) + return TRUE; + + for (i = 0; servers[i]; i++) + add_string_item(rc->nameservers, servers[i], TRUE); return TRUE; } @@ -1258,19 +1265,21 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) static const char * get_nameserver_list(int addr_family, const NML3ConfigData *l3cd, NMStrBuf *tmp_strbuf) { - char buf[NM_UTILS_INET_ADDRSTRLEN]; - guint num; - guint i; - gconstpointer nameservers; + char buf[NM_INET_ADDRSTRLEN]; + guint num; + guint i; + const char *const *strarr; nm_str_buf_reset(tmp_strbuf); - nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num); + strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num); for (i = 0; i < num; i++) { - const NMIPAddr *addr; + NMIPAddr a; + + if (!nm_utils_dnsname_parse_assert(addr_family, strarr[i], NULL, &a, NULL)) + continue; - addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i); - nm_utils_inet_ntop(addr_family, addr->addr_ptr, buf); + nm_inet_ntop(addr_family, &a, buf); if (i > 0) nm_str_buf_append_c(tmp_strbuf, ' '); nm_str_buf_append(tmp_strbuf, buf); @@ -1311,7 +1320,8 @@ _collect_resolv_conf_data(NMDnsManager *self, if (global_config) merge_global_dns_config(&rc, global_config); - else { + + if (!global_config || !nm_global_dns_config_lookup_domain(global_config, "*")) { nm_auto_str_buf NMStrBuf tmp_strbuf = NM_STR_BUF_INIT(0, FALSE); int first_prio = 0; const NMDnsConfigIPData *ip_data; @@ -2090,8 +2100,7 @@ nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean s /* Certain hostnames we don't want to include in resolv.conf 'searches' */ if (hostname && nm_utils_is_specific_hostname(hostname) - && !g_str_has_suffix(hostname, ".in-addr.arpa") - && !nm_utils_ipaddr_is_valid(AF_UNSPEC, hostname)) { + && !g_str_has_suffix(hostname, ".in-addr.arpa") && !nm_inet_is_valid(AF_UNSPEC, hostname)) { domain = strchr(hostname, '.'); if (domain) { domain++; @@ -2555,14 +2564,12 @@ config_changed_cb(NMConfig *config, } } -static GVariant * -_get_global_config_variant(NMGlobalDnsConfig *global) +static void +_get_global_config_variant(GVariantBuilder *builder, NMGlobalDnsConfig *global) { NMGlobalDnsDomain *domain; - GVariantBuilder builder; guint i, num; - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); num = nm_global_dns_config_get_num_domains(global); for (i = 0; i < num; i++) { GVariantBuilder conf_builder; @@ -2598,10 +2605,8 @@ _get_global_config_variant(NMGlobalDnsConfig *global) "priority", g_variant_new_int32(NM_DNS_PRIORITY_DEFAULT_NORMAL)); - g_variant_builder_add(&builder, "a{sv}", &conf_builder); + g_variant_builder_add(builder, "a{sv}", &conf_builder); } - - return g_variant_ref_sink(g_variant_builder_end(&builder)); } static GVariant * @@ -2618,28 +2623,25 @@ _get_config_variant(NMDnsManager *self) if (priv->config_variant) return priv->config_variant; - global_config = nm_config_data_get_global_dns_config(nm_config_get_data(priv->config)); - if (global_config) { - priv->config_variant = _get_global_config_variant(global_config); - _LOGT("current configuration: %s", (str = g_variant_print(priv->config_variant, TRUE))); - return priv->config_variant; - } - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + global_config = nm_config_data_get_global_dns_config(nm_config_get_data(priv->config)); + if (global_config) + _get_global_config_variant(&builder, global_config); + 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); + GVariantBuilder entry_builder; + GVariantBuilder strv_builder; + guint num; + guint num_domains; + guint num_searches; + guint i; + char buf[NM_INET_ADDRSTRLEN]; + const char *ifname; + const char *const *strarr; + + strarr = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num); if (num == 0) continue; @@ -2647,12 +2649,12 @@ _get_config_variant(NMDnsManager *self) g_variant_builder_init(&strv_builder, G_VARIANT_TYPE("as")); for (i = 0; i < num; i++) { - const NMIPAddr *addr; + NMIPAddr a; + + if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, NULL)) + continue; - 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(&strv_builder, "s", nm_inet_ntop(ip_data->addr_family, &a, buf)); } g_variant_builder_add(&entry_builder, "{sv}", diff --git a/src/core/dns/nm-dns-manager.h b/src/core/dns/nm-dns-manager.h index 210f9f6c..42f9dec5 100644 --- a/src/core/dns/nm-dns-manager.h +++ b/src/core/dns/nm-dns-manager.h @@ -12,16 +12,6 @@ #include "nm-setting-connection.h" #include "nm-dns-plugin.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, -} NMDnsIPConfigType; - -/*****************************************************************************/ - struct _NMDnsConfigData; struct _NMDnsManager; @@ -71,7 +61,7 @@ typedef struct _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(o) (_NM_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)) #define NM_IS_DNS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), NM_TYPE_DNS_MANAGER)) diff --git a/src/core/dns/nm-dns-plugin.h b/src/core/dns/nm-dns-plugin.h index 24d6083b..364f15ce 100644 --- a/src/core/dns/nm-dns-plugin.h +++ b/src/core/dns/nm-dns-plugin.h @@ -11,7 +11,7 @@ #include "nm-config-data.h" #define NM_TYPE_DNS_PLUGIN (nm_dns_plugin_get_type()) -#define NM_DNS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNS_PLUGIN, NMDnsPlugin)) +#define NM_DNS_PLUGIN(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNS_PLUGIN, NMDnsPlugin)) #define NM_DNS_PLUGIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DNS_PLUGIN, NMDnsPluginClass)) #define NM_IS_DNS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DNS_PLUGIN)) diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index e0b94647..24c7c774 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -36,6 +36,7 @@ /* define a variable, so that we can compare the operation with pointer equality. */ static const char *const DBUS_OP_SET_LINK_DEFAULT_ROUTE = "SetLinkDefaultRoute"; static const char *const DBUS_OP_SET_LINK_DNS_OVER_TLS = "SetLinkDNSOverTLS"; +static const char *const DBUS_OP_SET_LINK_DNS_EX = "SetLinkDNSEx"; /*****************************************************************************/ @@ -90,12 +91,11 @@ typedef struct { bool dbus_initied : 1; bool send_updates_waiting : 1; bool update_pending : 1; - /* These two variables ensure that the log is not spammed with - * API (not) supported messages. - * They can be removed when no distro uses systemd-resolved < v240 anymore - */ - NMTernary has_link_default_route : 3; - NMTernary has_link_dns_over_tls : 3; + + /* Detect support for the respective D-Bus API. */ + NMTernary has_set_link_default_route : 3; + NMTernary has_set_link_dns_over_tls : 3; + NMTernary has_set_link_dns_ex : 3; } NMDnsSystemdResolvedPrivate; struct _NMDnsSystemdResolved { @@ -148,6 +148,8 @@ static void _resolve_complete_error(NMDnsSystemdResolvedResolveHandle *handle, G static void _resolve_start(NMDnsSystemdResolved *self, NMDnsSystemdResolvedResolveHandle *handle); +static void send_updates(NMDnsSystemdResolved *self); + /*****************************************************************************/ static gboolean @@ -276,6 +278,7 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) NMLogLevel log_level; const char *operation; int ifindex; + gboolean reconfigure = FALSE; request_item = user_data; self = request_item->self; @@ -290,30 +293,52 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) goto out_dec_pending; if (v) { - if (operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE - && priv->has_link_default_route == NM_TERNARY_DEFAULT) { - priv->has_link_default_route = NM_TERNARY_TRUE; - _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API supported"); - } - if (operation == DBUS_OP_SET_LINK_DNS_OVER_TLS - && priv->has_link_dns_over_tls == NM_TERNARY_DEFAULT) { - priv->has_link_dns_over_tls = NM_TERNARY_TRUE; - _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API supported"); + if (operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) { + if (priv->has_set_link_default_route == NM_TERNARY_DEFAULT) { + priv->has_set_link_default_route = NM_TERNARY_TRUE; + _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API supported"); + } + } else if (operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) { + if (priv->has_set_link_dns_over_tls == NM_TERNARY_DEFAULT) { + priv->has_set_link_dns_over_tls = NM_TERNARY_TRUE; + _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API supported"); + } + } else if (operation == DBUS_OP_SET_LINK_DNS_EX) { + if (priv->has_set_link_dns_ex == NM_TERNARY_DEFAULT) { + priv->has_set_link_dns_ex = NM_TERNARY_TRUE; + _LOGD("systemd-resolved support for SetLinkDNSEx(): API supported"); + } } priv->send_updates_warn_ratelimited = FALSE; goto out_dec_pending; } if (nm_g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) { - if (priv->has_link_default_route == NM_TERNARY_DEFAULT - && operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) { - priv->has_link_default_route = NM_TERNARY_FALSE; - _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API not supported"); - } - if (priv->has_link_dns_over_tls == NM_TERNARY_DEFAULT - && operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) { - priv->has_link_dns_over_tls = NM_TERNARY_FALSE; - _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API not supported"); + if (operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) { + if (priv->has_set_link_default_route == NM_TERNARY_DEFAULT) { + priv->has_set_link_default_route = NM_TERNARY_FALSE; + _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API not supported"); + } + } else if (operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) { + if (priv->has_set_link_dns_over_tls == NM_TERNARY_DEFAULT) { + priv->has_set_link_dns_over_tls = NM_TERNARY_FALSE; + _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API not supported"); + } + } else if (operation == DBUS_OP_SET_LINK_DNS_EX) { + if (priv->has_set_link_dns_ex == NM_TERNARY_DEFAULT) { + priv->has_set_link_dns_ex = NM_TERNARY_FALSE; + _LOGD("systemd-resolved support for SetLinkDNSEx(): API not supported"); + + _LOGW("systemd-resolved does not support SetLinkDNSEx API (v246). " + "Cannot set DoT server name (SNI)"); + + /* We need to reconfigure with the SetLinkDNS fallback. + * + * In the other cases above, there is no need to reconfigure anything. + * We won't retry SetLinkDefaultRoute/SetLinkDNSOverTLS anymore, but there + * is nothing else we can do about that. */ + reconfigure = TRUE; + } } goto out_dec_pending; } @@ -335,21 +360,29 @@ out_dec_pending: * we must wrap up fast, and not hang an undefined amount time. */ g_object_unref(self); } + + if (reconfigure) { + priv->send_updates_waiting = TRUE; + send_updates(self); + } } static gboolean update_add_ip_config(NMDnsSystemdResolved *self, + const NMDnsConfigIPData *ip_data, GVariantBuilder *dns, + GVariantBuilder *dns_ex, GVariantBuilder *domains, - const NMDnsConfigIPData *ip_data) + gboolean *out_require_dns_ex) { - gsize addr_size; - guint n; - guint i; - gboolean is_routing; - const char *domain; - gboolean has_config = FALSE; - gconstpointer nameservers; + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + gsize addr_size; + guint n; + guint i; + gboolean is_routing; + const char *domain; + gboolean has_config = FALSE; + const char *const *strarr; addr_size = nm_utils_addr_family_to_size(ip_data->addr_family); @@ -361,29 +394,52 @@ update_add_ip_config(NMDnsSystemdResolved *self, return FALSE; } - nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &n); + strarr = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &n); for (i = 0; i < n; i++) { - g_variant_builder_open(dns, G_VARIANT_TYPE("(iay)")); - g_variant_builder_add(dns, "i", ip_data->addr_family); - g_variant_builder_add_value( - dns, - nm_g_variant_new_ay(nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i), - addr_size)); - g_variant_builder_close(dns); - has_config = TRUE; - } + const char *server_name; + NMIPAddr a; + + if (!nm_utils_dnsname_parse_assert(ip_data->addr_family, strarr[i], NULL, &a, &server_name)) + continue; - if (!ip_data->domains.has_default_route_explicit - && ip_data->domains.has_default_route_exclusive) { - g_variant_builder_add(domains, "(sb)", ".", TRUE); + if (server_name) { + NM_SET_OUT(out_require_dns_ex, TRUE); + if (priv->has_set_link_dns_ex == FALSE) { + /* The caller won't care about this result anymore. We can skip setting it. */ + dns = NULL; + } + } + + if (dns_ex) { + g_variant_builder_open(dns_ex, G_VARIANT_TYPE("(iayqs)")); + g_variant_builder_add(dns_ex, "i", ip_data->addr_family); + g_variant_builder_add_value(dns_ex, nm_g_variant_new_ay((gconstpointer) &a, addr_size)); + g_variant_builder_add(dns_ex, "q", 0); + g_variant_builder_add(dns_ex, "s", server_name ?: ""); + g_variant_builder_close(dns_ex); + } + if (dns) { + g_variant_builder_open(dns, G_VARIANT_TYPE("(iay)")); + g_variant_builder_add(dns, "i", ip_data->addr_family); + g_variant_builder_add_value(dns, nm_g_variant_new_ay((gconstpointer) &a, addr_size)); + g_variant_builder_close(dns); + } has_config = TRUE; } - if (ip_data->domains.search) { - for (i = 0; ip_data->domains.search[i]; i++) { - domain = nm_utils_parse_dns_domain(ip_data->domains.search[i], &is_routing); - g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing); + + if (!has_config || domains) { + if (!ip_data->domains.has_default_route_explicit + && ip_data->domains.has_default_route_exclusive) { + g_variant_builder_add(domains, "(sb)", ".", TRUE); has_config = TRUE; } + if (ip_data->domains.search) { + for (i = 0; ip_data->domains.search[i]; i++) { + domain = nm_utils_parse_dns_domain(ip_data->domains.search[i], &is_routing); + g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing); + has_config = TRUE; + } + } } return has_config; @@ -406,7 +462,9 @@ free_pending_updates(NMDnsSystemdResolved *self) static gboolean prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) { + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); GVariantBuilder dns; + GVariantBuilder dns_ex; GVariantBuilder domains; NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; @@ -417,6 +475,9 @@ prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) gboolean has_config = FALSE; gboolean has_default_route = FALSE; guint i; + gboolean require_dns_ex = FALSE; + + nm_assert(ic->ifindex != NM_LOOPBACK_IFINDEX); g_variant_builder_init(&dns, G_VARIANT_TYPE("(ia(iay))")); g_variant_builder_add(&dns, "i", ic->ifindex); @@ -430,7 +491,7 @@ prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) for (i = 0; i < ic->ip_data_list->len; i++) { const NMDnsConfigIPData *ip_data = ic->ip_data_list->pdata[i]; - if (update_add_ip_config(self, &dns, &domains, ip_data)) + if (update_add_ip_config(self, ip_data, &dns, NULL, &domains, &require_dns_ex)) has_config = TRUE; if (ip_data->domains.has_default_route) @@ -448,6 +509,23 @@ prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) g_variant_builder_close(&dns); g_variant_builder_close(&domains); + if (!require_dns_ex) { + /* No need to use the new API. SetLinkDNS() is sufficient. */ + } else if (!priv->has_set_link_dns_ex) { + /* API to set server name is not supported. Nothing we can do. */ + require_dns_ex = FALSE; + } else { + g_variant_builder_init(&dns_ex, G_VARIANT_TYPE("(ia(iayqs))")); + g_variant_builder_add(&dns_ex, "i", ic->ifindex); + g_variant_builder_open(&dns_ex, G_VARIANT_TYPE("a(iayqs)")); + for (i = 0; i < ic->ip_data_list->len; i++) { + const NMDnsConfigIPData *ip_data = ic->ip_data_list->pdata[i]; + + update_add_ip_config(self, ip_data, NULL, &dns_ex, NULL, NULL); + } + g_variant_builder_close(&dns_ex); + } + switch (mdns) { case NM_SETTING_CONNECTION_MDNS_NO: mdns_arg = "no"; @@ -513,7 +591,14 @@ prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic) "SetLinkLLMNR", ic->ifindex, g_variant_new("(is)", ic->ifindex, llmnr_arg ?: "")); - _request_item_append(self, "SetLinkDNS", ic->ifindex, g_variant_builder_end(&dns)); + if (require_dns_ex) { + _request_item_append(self, + DBUS_OP_SET_LINK_DNS_EX, + ic->ifindex, + g_variant_builder_end(&dns_ex)); + g_variant_builder_clear(&dns); + } else + _request_item_append(self, "SetLinkDNS", ic->ifindex, g_variant_builder_end(&dns)); _request_item_append(self, DBUS_OP_SET_LINK_DNS_OVER_TLS, ic->ifindex, @@ -631,9 +716,9 @@ send_updates(NMDnsSystemdResolved *self) gs_free char *ss = NULL; if ((request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE - && priv->has_link_default_route == NM_TERNARY_FALSE) + && priv->has_set_link_default_route == NM_TERNARY_FALSE) || (request_item->operation == DBUS_OP_SET_LINK_DNS_OVER_TLS - && priv->has_link_dns_over_tls == NM_TERNARY_FALSE)) { + && priv->has_set_link_dns_over_tls == NM_TERNARY_FALSE)) { /* The "SetLinkDefaultRoute" API is only supported since v240. * The "SetLinkDNSOverTLS" API is only supported since v239. * We detected whether they are supported, and skip the calls. There @@ -708,6 +793,13 @@ update(NMDnsPlugin *plugin, nm_assert(ifindex == nm_l3_config_data_get_ifindex(ip_data->l3cd)); + if (ifindex == NM_LOOPBACK_IFINDEX) { + /* systemd-resolved API is per-link, and loopback is not supported. + * Unclear what to do about DNS configuration on loopback. Just skip + * it here. */ + continue; + } + ic = g_hash_table_lookup(interfaces, GINT_TO_POINTER(ifindex)); if (!ic) { ic = g_slice_new(InterfaceConfig); @@ -759,7 +851,7 @@ update(NMDnsPlugin *plugin, if (dirty_array) { g_array_sort_with_data(dirty_array, nm_cmp_int2ptr_p_with_data, NULL); for (i = 0; i < dirty_array->len; i++) { - int ifindex = g_array_index(dirty_array, int, i); + int ifindex = nm_g_array_index(dirty_array, int, i); InterfaceConfig ic; _LOGT("clear previously configured ifindex %d", ifindex); @@ -798,8 +890,9 @@ name_owner_changed(NMDnsSystemdResolved *self, const char *owner) priv->try_start_blocked = FALSE; priv->send_updates_waiting = TRUE; } else { - priv->has_link_default_route = NM_TERNARY_DEFAULT; - priv->has_link_dns_over_tls = NM_TERNARY_DEFAULT; + priv->has_set_link_default_route = NM_TERNARY_DEFAULT; + priv->has_set_link_dns_over_tls = NM_TERNARY_DEFAULT; + priv->has_set_link_dns_ex = NM_TERNARY_DEFAULT; } send_updates(self); @@ -968,7 +1061,7 @@ _resolve_handle_call_cb(GObject *source, GAsyncResult *result, gpointer user_dat g_variant_iter_free(v_names_iter); _resolve_complete(handle, - &g_array_index(v_names, NMDnsSystemdResolvedAddressResult, 0), + nm_g_array_first_p(v_names, NMDnsSystemdResolvedAddressResult), v_names->len, v_flags, NULL); @@ -1066,7 +1159,7 @@ nm_dns_systemd_resolved_resolve_address(NMDnsSystemdResolved { NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); NMDnsSystemdResolvedResolveHandle *handle; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + char addr_str[NM_INET_ADDRSTRLEN]; g_return_val_if_fail(NM_IS_DNS_SYSTEMD_RESOLVED(self), NULL); nm_assert_addr_family(addr_family); @@ -1092,7 +1185,7 @@ nm_dns_systemd_resolved_resolve_address(NMDnsSystemdResolved _LOG2T(handle, "resolve-address(ifindex=%d, %s, flags=%" G_GINT64_MODIFIER "x): new request", handle->r_address.ifindex, - nm_utils_inet_ntop(handle->r_address.addr_family, &handle->r_address.addr, addr_str), + nm_inet_ntop(handle->r_address.addr_family, &handle->r_address.addr, addr_str), handle->r_address.flags); _resolve_start(self, handle); @@ -1158,8 +1251,9 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self) { NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); - priv->has_link_default_route = NM_TERNARY_DEFAULT; - priv->has_link_dns_over_tls = NM_TERNARY_DEFAULT; + priv->has_set_link_default_route = NM_TERNARY_DEFAULT; + priv->has_set_link_dns_over_tls = NM_TERNARY_DEFAULT; + priv->has_set_link_dns_ex = NM_TERNARY_DEFAULT; c_list_init(&priv->request_queue_lst_head); c_list_init(&priv->handle_lst_head); diff --git a/src/core/dns/nm-dns-systemd-resolved.h b/src/core/dns/nm-dns-systemd-resolved.h index 02bc524c..0563a70f 100644 --- a/src/core/dns/nm-dns-systemd-resolved.h +++ b/src/core/dns/nm-dns-systemd-resolved.h @@ -12,7 +12,7 @@ #define NM_TYPE_DNS_SYSTEMD_RESOLVED (nm_dns_systemd_resolved_get_type()) #define NM_DNS_SYSTEMD_RESOLVED(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNS_SYSTEMD_RESOLVED, NMDnsSystemdResolved)) + (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNS_SYSTEMD_RESOLVED, NMDnsSystemdResolved)) #define NM_DNS_SYSTEMD_RESOLVED_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DNS_SYSTEMD_RESOLVED, NMDnsSystemdResolvedClass)) #define NM_IS_DNS_SYSTEMD_RESOLVED(obj) \ |