diff --git a/man/org.freedesktop.resolve1.xml b/man/org.freedesktop.resolve1.xml
index aa24d35123..c70e5c1cb3 100644
--- a/man/org.freedesktop.resolve1.xml
+++ b/man/org.freedesktop.resolve1.xml
@@ -440,35 +440,36 @@ node /org/freedesktop/resolve1 {
and recommended. However, the following flags are defined to alter the look-up:
/* Input+Output: Protocol/scope */
-#define SD_RESOLVED_DNS (UINT64_C(1) << 0)
-#define SD_RESOLVED_LLMNR_IPV4 (UINT64_C(1) << 1)
-#define SD_RESOLVED_LLMNR_IPV6 (UINT64_C(1) << 2)
-#define SD_RESOLVED_MDNS_IPV4 (UINT64_C(1) << 3)
-#define SD_RESOLVED_MDNS_IPV6 (UINT64_C(1) << 4)
+#define SD_RESOLVED_DNS (UINT64_C(1) << 0)
+#define SD_RESOLVED_LLMNR_IPV4 (UINT64_C(1) << 1)
+#define SD_RESOLVED_LLMNR_IPV6 (UINT64_C(1) << 2)
+#define SD_RESOLVED_MDNS_IPV4 (UINT64_C(1) << 3)
+#define SD_RESOLVED_MDNS_IPV6 (UINT64_C(1) << 4)
/* Input: Restrictions */
-#define SD_RESOLVED_NO_CNAME (UINT64_C(1) << 5)
-#define SD_RESOLVED_NO_TXT (UINT64_C(1) << 6)
-#define SD_RESOLVED_NO_ADDRESS (UINT64_C(1) << 7)
-#define SD_RESOLVED_NO_SEARCH (UINT64_C(1) << 8)
-#define SD_RESOLVED_NO_VALIDATE (UINT64_C(1) << 10)
-#define SD_RESOLVED_NO_SYNTHESIZE (UINT64_C(1) << 11)
-#define SD_RESOLVED_NO_CACHE (UINT64_C(1) << 12)
-#define SD_RESOLVED_NO_ZONE (UINT64_C(1) << 13)
-#define SD_RESOLVED_NO_TRUST_ANCHOR (UINT64_C(1) << 14)
-#define SD_RESOLVED_NO_NETWORK (UINT64_C(1) << 15)
-#define SD_RESOLVED_NO_STALE (UINT64_C(1) << 24)
+#define SD_RESOLVED_NO_CNAME (UINT64_C(1) << 5)
+#define SD_RESOLVED_NO_TXT (UINT64_C(1) << 6)
+#define SD_RESOLVED_NO_ADDRESS (UINT64_C(1) << 7)
+#define SD_RESOLVED_NO_SEARCH (UINT64_C(1) << 8)
+#define SD_RESOLVED_NO_VALIDATE (UINT64_C(1) << 10)
+#define SD_RESOLVED_NO_SYNTHESIZE (UINT64_C(1) << 11)
+#define SD_RESOLVED_NO_CACHE (UINT64_C(1) << 12)
+#define SD_RESOLVED_NO_ZONE (UINT64_C(1) << 13)
+#define SD_RESOLVED_NO_TRUST_ANCHOR (UINT64_C(1) << 14)
+#define SD_RESOLVED_NO_NETWORK (UINT64_C(1) << 15)
+#define SD_RESOLVED_NO_STALE (UINT64_C(1) << 24)
+#define SD_RESOLVED_RELAX_SINGLE_LABEL (UINT64_C(1) << 25)
/* Output: Security */
-#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9)
-#define SD_RESOLVED_CONFIDENTIAL (UINT64_C(1) << 18)
+#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9)
+#define SD_RESOLVED_CONFIDENTIAL (UINT64_C(1) << 18)
/* Output: Origin */
-#define SD_RESOLVED_SYNTHETIC (UINT64_C(1) << 19)
-#define SD_RESOLVED_FROM_CACHE (UINT64_C(1) << 20)
-#define SD_RESOLVED_FROM_ZONE (UINT64_C(1) << 21)
-#define SD_RESOLVED_FROM_TRUST_ANCHOR (UINT64_C(1) << 22)
-#define SD_RESOLVED_FROM_NETWORK (UINT64_C(1) << 23)
+#define SD_RESOLVED_SYNTHETIC (UINT64_C(1) << 19)
+#define SD_RESOLVED_FROM_CACHE (UINT64_C(1) << 20)
+#define SD_RESOLVED_FROM_ZONE (UINT64_C(1) << 21)
+#define SD_RESOLVED_FROM_TRUST_ANCHOR (UINT64_C(1) << 22)
+#define SD_RESOLVED_FROM_NETWORK (UINT64_C(1) << 23)
On input, the first five flags control the protocols to use for the look-up. They refer to
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index f83c654558..be2fdca21f 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -373,6 +373,7 @@ static int validate_and_mangle_flags(
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
SD_RESOLVED_NO_STALE|
+ SD_RESOLVED_RELAX_SINGLE_LABEL|
ok))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
diff --git a/src/resolve/resolved-def.h b/src/resolve/resolved-def.h
index b7a44f9571..f702a0a0ea 100644
--- a/src/resolve/resolved-def.h
+++ b/src/resolve/resolved-def.h
@@ -73,6 +73,10 @@
/* Input: Don't answer request with stale data */
#define SD_RESOLVED_NO_STALE (UINT64_C(1) << 24)
+/* Input: Allow single-label lookups to Internet DNS servers */
+#define SD_RESOLVED_RELAX_SINGLE_LABEL \
+ (UINT64_C(1) << 25)
+
#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6)
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index 938dd61a6a..cb2368c67a 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -741,7 +741,7 @@ int dns_query_go(DnsQuery *q) {
LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
DnsScopeMatch match;
- match = dns_scope_good_domain(s, q);
+ match = dns_scope_good_domain(s, q, q->flags);
assert(match >= 0);
if (match > found) { /* Does this match better? If so, remember how well it matched, and the first one
* that matches this well */
@@ -768,7 +768,7 @@ int dns_query_go(DnsQuery *q) {
LIST_FOREACH(scopes, s, first->scopes_next) {
DnsScopeMatch match;
- match = dns_scope_good_domain(s, q);
+ match = dns_scope_good_domain(s, q, q->flags);
assert(match >= 0);
if (match < found)
continue;
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index e390715807..94c7674a8f 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -593,7 +593,8 @@ static DnsScopeMatch match_subnet_reverse_lookups(
DnsScopeMatch dns_scope_good_domain(
DnsScope *s,
- DnsQuery *q) {
+ DnsQuery *q,
+ uint64_t query_flags) {
DnsQuestion *question;
const char *domain;
@@ -707,7 +708,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 */
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index ca33fd007a..e2eb023c1d 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -76,7 +76,7 @@ int dns_scope_emit_udp(DnsScope *s, int fd, int af, DnsPacket *p);
int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port, union sockaddr_union *ret_socket_address);
int dns_scope_socket_udp(DnsScope *s, DnsServer *server);
-DnsScopeMatch dns_scope_good_domain(DnsScope *s, DnsQuery *q);
+DnsScopeMatch dns_scope_good_domain(DnsScope *s, DnsQuery *q, uint64_t query_flags);
bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key);
DnsServer *dns_scope_get_dns_server(DnsScope *s);
diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c
index 6e6e973f94..cdd5ca41fd 100644
--- a/src/resolve/resolved-varlink.c
+++ b/src/resolve/resolved-varlink.c
@@ -162,6 +162,7 @@ static bool validate_and_mangle_flags(
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
SD_RESOLVED_NO_STALE|
+ SD_RESOLVED_RELAX_SINGLE_LABEL|
ok))
return false;