diff options
Diffstat (limited to 'src/resolve/resolved-bus.c')
-rw-r--r-- | src/resolve/resolved-bus.c | 82 |
1 files changed, 73 insertions, 9 deletions
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index fc5e6beca0..6f08c43327 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -23,6 +23,7 @@ #include "dns-domain.h" #include "resolved-bus.h" #include "resolved-def.h" +#include "resolved-dns-synthesize.h" #include "resolved-link-bus.h" static int reply_query_state(DnsQuery *q) { @@ -233,6 +234,65 @@ static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus return 0; } +static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname, int family, uint64_t flags) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *canonical = NULL; + union in_addr_union parsed; + int r, ff; + + /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it, + * let's not attempt to look it up. */ + + r = in_addr_from_string_auto(hostname, &ff, &parsed); + if (r < 0) /* not an address */ + return 0; + + if (family != AF_UNSPEC && ff != family) + return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address is not of the requested family."); + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(iiay)"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'r', "iiay"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "ii", ifindex, ff); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &parsed, FAMILY_ADDRESS_SIZE(ff)); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS + * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner + * omissions are always done the same way). */ + r = in_addr_to_string(ff, &parsed, &canonical); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "st", canonical, + SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true)); + if (r < 0) + return r; + + return sd_bus_send(sd_bus_message_get_bus(m), reply, NULL); +} + static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL; Manager *m = userdata; @@ -254,15 +314,19 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); - r = dns_name_is_valid(hostname); + r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error); if (r < 0) return r; - if (r == 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname); - r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error); + r = parse_as_address(message, ifindex, hostname, family, flags); + if (r != 0) + return r; + + r = dns_name_is_valid(hostname); if (r < 0) return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname); r = dns_question_new_address(&question_utf8, family, hostname, false); if (r < 0) @@ -1198,7 +1262,7 @@ static int bus_property_get_dns_servers( return sd_bus_message_close_container(reply); } -static int bus_property_get_search_domains( +static int bus_property_get_domains( sd_bus *bus, const char *path, const char *interface, @@ -1396,8 +1460,8 @@ static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userda return call_link_method(userdata, message, bus_link_method_set_dns_servers, error); } -static int bus_method_set_link_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { - return call_link_method(userdata, message, bus_link_method_set_search_domains, error); +static int bus_method_set_link_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_domains, error); } static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -1449,7 +1513,7 @@ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0), SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0), - SD_BUS_PROPERTY("SearchDomains", "a(isb)", bus_property_get_search_domains, 0, 0), + SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0), SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0), SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0), SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0), @@ -1462,7 +1526,7 @@ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0), SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0), - SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_search_domains, 0), + SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, 0), SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0), SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0), SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0), |