resolved-dns-query.c revision 801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47dd
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann This file is part of systemd.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Copyright 2014 Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann systemd is free software; you can redistribute it and/or modify it
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann under the terms of the GNU Lesser General Public License as published by
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann the Free Software Foundation; either version 2.1 of the License, or
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann (at your option) any later version.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann systemd is distributed in the hope that it will be useful, but
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann WITHOUT ANY WARRANTY; without even the implied warranty of
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Lesser General Public License for more details.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann You should have received a copy of the GNU Lesser General Public License
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann along with systemd; If not, see <http://www.gnu.org/licenses/>.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann/* How long to wait for the query in total */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_PREPEND(candidates_by_query, q->candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_PREPEND(candidates_by_scope, s->query_candidates, c);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic void dns_query_candidate_stop(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann while ((t = set_steal_first(c->transactions))) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid HerrmannDnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_REMOVE(candidates_by_query, c->query->candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann _cleanup_(dns_search_domain_unrefp) DnsSearchDomain *previous = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (c->search_domain && c->search_domain->linked) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* We hit the last entry. Let's see if this
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * was the per-link search domain list. If so,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * let's continue with the global one. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (c->search_domain->type == DNS_SEARCH_DOMAIN_LINK)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!next) /* Still no item? Then we really hit the end of the list. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* If we have, start with the per-link domains */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann next = dns_scope_get_search_domains(c->scope);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!next) /* Fall back to the global search domains */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann c->search_domain = dns_search_domain_ref(next);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = set_ensure_allocated(&c->transactions, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann t = dns_scope_find_transaction(c->scope, key, true);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = set_ensure_allocated(&t->query_candidates, NULL);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic int dns_query_candidate_go(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Start the transactions that are not started yet */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann switch (t->state) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int n = 0, r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Create one transaction per question key */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DNS_QUESTION_FOREACH(key, c->query->question) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_resource_key_unrefp) DnsResourceKey *new_key = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_resource_key_new_append_suffix(&new_key, key, c->search_domain->name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_add_transaction(c, new_key ?: key);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannvoid dns_query_candidate_ready(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (IN_SET(state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (state != DNS_TRANSACTION_SUCCESS && c->search_domain) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_next_search_domain(c);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering /* OK, there's another search domain to try, let's do so. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_setup_transactions(c);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann /* New transactions where queued. Start them and wait */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_warning_errno(r, "Failed to follow search domains: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_FOREACH(candidates_by_query, c, q->candidates)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q->auxiliary_for->n_auxiliary_queries > 0);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann dns_search_domain_unref(q->answer_search_domain);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_REMOVE(queries, q->manager->dns_queries, q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannint dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering _cleanup_(dns_query_freep) DnsQuery *q = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_question_is_valid_for_query(question);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_resource_key_to_string(question->keys[i], &p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannint dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Ensure that that the query is not auxiliary yet, and
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * nothing else is auxiliary to it either */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Ensure that the unit we shall be made auxiliary for isn't
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * auxiliary itself */
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Note that this call might invalidate the query. Callers
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * should hence not attempt to access the query or transaction
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * after calling this function. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
1140e154100f7224fb8bab55ba7fc087409f9d76Lennart Poetteringstatic int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* If this a single-label domain on DNS, we might append a suitable search domain first. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_scope_name_needs_search_domain(s, dns_question_first_name(q->question));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* OK, we need a search domain now. Let's find one for this scope */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_next_search_domain(c);
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann if (r <= 0) /* if there's no search domain, then we won't add any transaction. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_setup_transactions(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* When the caller asked for resolving on a specific
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * interface, we synthesize the answer for that
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * interface. However, if nothing specific was claimed and we
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * only return localhost RRs, we synthesize the answer for
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * localhost. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int SYNTHESIZE_FAMILY(uint64_t flags) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Picks an address family depending on set flags. This is
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * purely for synthesized answers, where the family we return
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann * for the reply should match what was requested in the
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * question, even though we are synthesizing the answer
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann /* Similar as SYNTHESIZE_FAMILY() but does this for the
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * protocol. If resolving via DNS was requested, we claim it
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * was DNS. Similar, if nothing specific was
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * requested. However, if only resolving via LLMNR was
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * requested we return that. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (j = 0; j < n_addresses; j++) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_add(*answer, rr, addresses[j].ifindex);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (j = 0; j < n_addresses; j++) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (match && !in_addr_equal(af, match, &addresses[j].address))
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_add(*answer, rr, addresses[j].ifindex);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ struct local_address *addresses = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (n == 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* If we have no local addresses then use ::1
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering * and 127.0.0.2 as local ones. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ struct local_address *addresses = NULL;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Always map the IPv4 address 127.0.0.2 to the local
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * hostname, in addition to "localhost": */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ struct local_address *addresses = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ struct local_address *addresses = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Tries to synthesize localhost RR replies where appropriate */
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering for (i = 0; i < q->question->n_keys; i++) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (q->question->keys[i]->class != DNS_CLASS_IN &&
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->question->keys[i]->class != DNS_CLASS_ANY)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
} else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
if (!answer)
const char *name;
assert(q);
if (match < 0)
return match;
first = s;
if (!first)
first = s;
goto fail;
if (match < 0)
goto fail;
r = dns_query_add_candidate(q, s);
goto fail;
q->answer_rcode = 0;
r = sd_event_add_time(
&q->timeout_event_source,
on_query_timeout, q);
goto fail;
q->block_ready++;
r = dns_query_candidate_go(c);
q->block_ready--;
goto fail;
q->block_ready--;
dns_query_ready(q);
fail:
dns_query_stop(q);
DnsTransaction *t;
Iterator i;
assert(q);
switch (t->state) {
case DNS_TRANSACTION_SUCCESS: {
if (t->received) {
a = t->cached;
if (!merged) {
case DNS_TRANSACTION_PENDING:
case DNS_TRANSACTION_NULL:
case DNS_TRANSACTION_ABORTED:
if (t->received) {
bool pending = false;
assert(q);
if (q->block_ready > 0)
switch (state) {
case DNS_TRANSACTION_SUCCESS:
dns_query_accept(q, c);
case DNS_TRANSACTION_PENDING:
case DNS_TRANSACTION_NULL:
pending = true;
bad = c;
if (pending)
assert(q);
q->n_cname_redirects ++;
return -ELOOP;
dns_query_stop(q);
assert(q);
if (r > 0 && !cname)
if (!cname)
return -ELOOP;
r = dns_query_go(q);
assert(t);
assert(q);
assert(q);
assert(m);
if (!q->bus_track) {