summaryrefslogtreecommitdiffstats
path: root/src/resolve/resolved-dns-scope.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve/resolved-dns-scope.c')
-rw-r--r--src/resolve/resolved-dns-scope.c92
1 files changed, 88 insertions, 4 deletions
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index af8e9cd..17bc823 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -12,6 +12,7 @@
#include "random-util.h"
#include "resolved-dnssd.h"
#include "resolved-dns-scope.h"
+#include "resolved-dns-synthesize.h"
#include "resolved-dns-zone.h"
#include "resolved-llmnr.h"
#include "resolved-mdns.h"
@@ -41,6 +42,7 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int
.protocol = protocol,
.family = family,
.resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC,
+ .mdns_goodbye_event_source = NULL,
};
if (protocol == DNS_PROTOCOL_DNS) {
@@ -115,6 +117,8 @@ DnsScope* dns_scope_free(DnsScope *s) {
sd_event_source_disable_unref(s->announce_event_source);
+ sd_event_source_disable_unref(s->mdns_goodbye_event_source);
+
dns_cache_flush(&s->cache);
dns_zone_flush(&s->zone);
@@ -616,12 +620,13 @@ static bool dns_refuse_special_use_domain(const char *domain, DnsQuestion *quest
DnsScopeMatch dns_scope_good_domain(
DnsScope *s,
- DnsQuery *q) {
+ DnsQuery *q,
+ uint64_t query_flags) {
DnsQuestion *question;
const char *domain;
uint64_t flags;
- int ifindex;
+ int ifindex, r;
/* This returns the following return values:
*
@@ -680,6 +685,15 @@ DnsScopeMatch dns_scope_good_domain(
is_dns_proxy_stub_hostname(domain))
return DNS_SCOPE_NO;
+ /* Don't look up the local host name via the network, unless user turned of local synthesis of it */
+ if (manager_is_own_hostname(s->manager, domain) && shall_synthesize_own_hostname_rrs())
+ return DNS_SCOPE_NO;
+
+ /* Never send SOA or NS or DNSSEC request to LLMNR, where they make little sense. */
+ r = dns_question_types_suitable_for_protocol(question, s->protocol);
+ if (r <= 0)
+ return DNS_SCOPE_NO;
+
switch (s->protocol) {
case DNS_PROTOCOL_DNS: {
@@ -735,7 +749,8 @@ DnsScopeMatch dns_scope_good_domain(
/* If ResolveUnicastSingleLabel=yes and the query is single-label, then bump match result
to prevent LLMNR monopoly among candidates. */
- if (s->manager->resolve_unicast_single_label && dns_name_is_single_label(domain))
+ if ((s->manager->resolve_unicast_single_label || (query_flags & SD_RESOLVED_RELAX_SINGLE_LABEL)) &&
+ dns_name_is_single_label(domain))
return DNS_SCOPE_YES_BASE + 1;
/* Let's return the number of labels in the best matching result */
@@ -1588,7 +1603,7 @@ int dns_scope_add_dnssd_services(DnsScope *scope) {
assert(scope);
- if (hashmap_size(scope->manager->dnssd_services) == 0)
+ if (hashmap_isempty(scope->manager->dnssd_services))
return 0;
scope->announced = false;
@@ -1600,6 +1615,12 @@ int dns_scope_add_dnssd_services(DnsScope *scope) {
if (r < 0)
log_warning_errno(r, "Failed to add PTR record to MDNS zone: %m");
+ if (service->sub_ptr_rr) {
+ r = dns_zone_put(&scope->zone, scope, service->sub_ptr_rr, false);
+ if (r < 0)
+ log_warning_errno(r, "Failed to add selective PTR record to MDNS zone: %m");
+ }
+
r = dns_zone_put(&scope->zone, scope, service->srv_rr, true);
if (r < 0)
log_warning_errno(r, "Failed to add SRV record to MDNS zone: %m");
@@ -1632,6 +1653,7 @@ int dns_scope_remove_dnssd_services(DnsScope *scope) {
HASHMAP_FOREACH(service, scope->manager->dnssd_services) {
dns_zone_remove_rr(&scope->zone, service->ptr_rr);
+ dns_zone_remove_rr(&scope->zone, service->sub_ptr_rr);
dns_zone_remove_rr(&scope->zone, service->srv_rr);
LIST_FOREACH(items, txt_data, service->txt_data_items)
dns_zone_remove_rr(&scope->zone, txt_data->rr);
@@ -1712,3 +1734,65 @@ int dns_scope_dump_cache_to_json(DnsScope *scope, JsonVariant **ret) {
JSON_BUILD_PAIR_CONDITION(scope->link, "ifname", JSON_BUILD_STRING(scope->link ? scope->link->ifname : NULL)),
JSON_BUILD_PAIR_VARIANT("cache", cache)));
}
+
+int dns_type_suitable_for_protocol(uint16_t type, DnsProtocol protocol) {
+
+ /* Tests whether it makes sense to route queries for the specified DNS RR types to the specified
+ * protocol. For classic DNS pretty much all RR types are suitable, but for LLMNR/mDNS let's
+ * allowlist only a few that make sense. We use this when routing queries so that we can more quickly
+ * return errors for queries that will almost certainly fail/time-out otherwise. For example, this
+ * ensures that SOA, NS, or DS/DNSKEY queries are never routed to mDNS/LLMNR where they simply make
+ * no sense. */
+
+ if (dns_type_is_obsolete(type))
+ return false;
+
+ if (!dns_type_is_valid_query(type))
+ return false;
+
+ switch (protocol) {
+
+ case DNS_PROTOCOL_DNS:
+ return true;
+
+ case DNS_PROTOCOL_LLMNR:
+ return IN_SET(type,
+ DNS_TYPE_ANY,
+ DNS_TYPE_A,
+ DNS_TYPE_AAAA,
+ DNS_TYPE_CNAME,
+ DNS_TYPE_PTR,
+ DNS_TYPE_TXT);
+
+ case DNS_PROTOCOL_MDNS:
+ return IN_SET(type,
+ DNS_TYPE_ANY,
+ DNS_TYPE_A,
+ DNS_TYPE_AAAA,
+ DNS_TYPE_CNAME,
+ DNS_TYPE_PTR,
+ DNS_TYPE_TXT,
+ DNS_TYPE_SRV,
+ DNS_TYPE_NSEC,
+ DNS_TYPE_HINFO);
+
+ default:
+ return -EPROTONOSUPPORT;
+ }
+}
+
+int dns_question_types_suitable_for_protocol(DnsQuestion *q, DnsProtocol protocol) {
+ DnsResourceKey *key;
+ int r;
+
+ /* Tests whether the types in the specified question make any sense to be routed to the specified
+ * protocol, i.e. if dns_type_suitable_for_protocol() is true for any of the contained RR types */
+
+ DNS_QUESTION_FOREACH(key, q) {
+ r = dns_type_suitable_for_protocol(key->type, protocol);
+ if (r != 0)
+ return r;
+ }
+
+ return false;
+}