From: Lennart Poettering Date: Fri, 6 Nov 2020 19:10:40 +0000 (+0100) Subject: resolvectl: clarify IDNA and search path logic in combination with "resolvectl query... X-Git-Tag: v248-rc1~113 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=018b642a98fc7d41ec7fa5157c9ce84677174ff5;p=thirdparty%2Fsystemd.git resolvectl: clarify IDNA and search path logic in combination with "resolvectl query --type=" When low-level RR resolution is requested from "resolvectl query" via "--type=" or "--class=" no search domain logic is applied and no IDNA translation. Explain this in detail in the documentation, and also mentions this when users attempt to resolve single-label names or names with international characters in the output. I believe the current behaviour is correct, but it is indeed surprising. Hence the documentation and output improvement. Fixes: #11325 #10737 --- diff --git a/man/resolvectl.xml b/man/resolvectl.xml index 7662349cc54..c87b6fd44b3 100644 --- a/man/resolvectl.xml +++ b/man/resolvectl.xml @@ -55,7 +55,19 @@ query HOSTNAME|ADDRESS… - Resolve domain names, IPv4 and IPv6 addresses. + Resolve domain names, as well as IPv4 and IPv6 addresses. When used in conjuntion + with or (see below), resolves low-level DNS + resource records. + + If a single-label domain name is specified it is searched for according to the configured + search domains — unless or + / are specified, both of which turn this logic + off. + + If an international domain name is specified, it is automatically translated according to IDNA + rules when resolved via classic DNS — but not for look-ups via MulticastDNS or LLMNR. If + / is used IDNA translation is turned off and domain + names are processed as specified. @@ -233,11 +245,19 @@ CLASS CLASS - Specifies the DNS resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to - look up. If these options are used a DNS resource record set matching the specified class and type is - requested. The class defaults to IN if only a type is specified. - The special value help may be used to list known values. - + When used in conjunction with the query command, specifies the DNS + resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to look up. If these options + are used a DNS resource record set matching the specified class and type is requested. The class + defaults to IN if only a type is specified. The special value help may be used to + list known values. + + Without these options resolvectl query provides high-level domain name to + address and address to domain name resolution. With these options it provides low-level DNS resource + record resolution. The search domain logic is automatically turned off when these options are used, + i.e. specified domain names need to be fully qualified domain names. Moreover, IDNA internal domain + name translation is turned off as well, i.e. international domain names should be specified in + xn--… notation, unless look-up in MulticastDNS/LLMNR is desired, in which case + UTF-8 characters should be used. @@ -324,9 +344,11 @@ BOOL - Takes a boolean parameter. If true (the default), any specified single-label hostnames will be - searched in the domains configured in the search domain list, if it is non-empty. Otherwise, the search domain - logic is disabled. + Takes a boolean parameter. If true (the default), any specified single-label + hostnames will be searched in the domains configured in the search domain list, if it is + non-empty. Otherwise, the search domain logic is disabled. Note that this option has no effect if + is used (see above), in which case the search domain logic is + unconditionally turned off. diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index e7ee7354287..6301b6ba09b 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -407,19 +407,51 @@ static int output_rr_packet(const void *d, size_t l, int ifindex) { return 0; } +static int idna_candidate(const char *name, char **ret) { + _cleanup_free_ char *idnafied = NULL; + int r; + + assert(name); + assert(ret); + + r = dns_name_apply_idna(name, &idnafied); + if (r < 0) + return log_error_errno(r, "Failed to apply IDNA to name '%s': %m", name); + if (r > 0 && !streq(name, idnafied)) { + *ret = TAKE_PTR(idnafied); + return true; + } + + *ret = NULL; + return false; +} + static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *idnafied = NULL; + bool needs_authentication = false; unsigned n = 0; uint64_t flags; - int r; usec_t ts; - bool needs_authentication = false; + int r; assert(name); log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(arg_ifname) ? "*" : arg_ifname); + if (dns_name_is_single_label(name)) + log_notice("(Note that search domains are not appended when resolving raw record types. " + "Please specify fully qualified domain names when resolving raw records, or remove --type= switch from invocation in order to request regular hostname resolution.)"); + + r = idna_candidate(name, &idnafied); + if (r < 0) + return r; + if (r > 0) + log_notice("(Note that IDNA translation is not applied when resolving raw record types. " + "Please specify translated domain names — i.e. '%s' — when resolving raw records, or remove --type= switch from invocation in order to request regular hostname resolution.", + idnafied); + r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveRecord"); if (r < 0) return bus_log_create_error(r);