resolved-dns-query.c revision 801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47dd
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann/***
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann This file is part of systemd.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Copyright 2014 Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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
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
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***/
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "alloc-util.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "dns-domain.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "hostname-util.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "local-addresses.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "resolved-dns-query.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann/* How long to wait for the query in total */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define CNAME_MAX 8
0a6f50c0afdfc434b492493bd9efab20cbee8623Thomas Hindoe Paaboel Andersen#define QUERIES_MAX 2048
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#define AUXILIARY_QUERIES_MAX 64
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsQueryCandidate *c;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(ret);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(s);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann c = new0(DnsQueryCandidate, 1);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!c)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann c->query = q;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann c->scope = s;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_PREPEND(candidates_by_query, q->candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_PREPEND(candidates_by_scope, s->query_candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann *ret = c;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic void dns_query_candidate_stop(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsTransaction *t;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann while ((t = set_steal_first(c->transactions))) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann set_remove(t->query_candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_transaction_gc(t);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid HerrmannDnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!c)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_candidate_stop(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann set_free(c->transactions);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_search_domain_unref(c->search_domain);
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (c->query)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_REMOVE(candidates_by_query, c->query->candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (c->scope)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann return NULL;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann}
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann _cleanup_(dns_search_domain_unrefp) DnsSearchDomain *previous = NULL;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann DnsSearchDomain *next = NULL;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (c->search_domain && c->search_domain->linked) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann next = c->search_domain->domains_next;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!next) {
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
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (c->search_domain->type == DNS_SEARCH_DOMAIN_LINK)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann next = c->query->manager->search_domains;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!next) /* Still no item? Then we really hit the end of the list. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann } else {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* If we have, start with the per-link domains */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann next = dns_scope_get_search_domains(c->scope);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!next) /* Fall back to the global search domains */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann next = c->scope->manager->search_domains;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!next) /* OK, there's really nothing. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_search_domain_unref(c->search_domain);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann c->search_domain = dns_search_domain_ref(next);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsTransaction *t;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(key);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = set_ensure_allocated(&c->transactions, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann t = dns_scope_find_transaction(c->scope, key, true);
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann if (!t) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_transaction_new(&t, c->scope, key);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = set_ensure_allocated(&t->query_candidates, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto gc;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = set_put(t->query_candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto gc;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = set_put(c->transactions, t);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann set_remove(t->query_candidates, c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto gc;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmanngc:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_transaction_gc(t);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic int dns_query_candidate_go(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsTransaction *t;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Iterator i;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Start the transactions that are not started yet */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann SET_FOREACH(t, c->transactions, i) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (t->state != DNS_TRANSACTION_NULL)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_transaction_go(t);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsTransaction *t;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Iterator i;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (c->error_code != 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return DNS_TRANSACTION_RESOURCES;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann SET_FOREACH(t, c->transactions, i) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann switch (t->state) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann case DNS_TRANSACTION_PENDING:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann case DNS_TRANSACTION_NULL:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return t->state;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann case DNS_TRANSACTION_SUCCESS:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann state = t->state;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering break;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann default:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (state != DNS_TRANSACTION_SUCCESS)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann state = t->state;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann break;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return state;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsResourceKey *key;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int n = 0, r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_candidate_stop(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (c->search_domain) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_resource_key_new_append_suffix(&new_key, key, c->search_domain->name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto fail;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_add_transaction(c, new_key ?: key);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto fail;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n++;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return n;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannfail:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_candidate_stop(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannvoid dns_query_candidate_ready(DnsQueryCandidate *c) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsTransactionState state;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann state = dns_query_candidate_state(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (IN_SET(state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (state != DNS_TRANSACTION_SUCCESS && c->search_domain) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_next_search_domain(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann goto fail;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r > 0) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering /* OK, there's another search domain to try, let's do so. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_setup_transactions(c);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (r < 0)
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann goto fail;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (r > 0) {
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann /* New transactions where queued. Start them and wait */
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann r = dns_query_candidate_go(c);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (r < 0)
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann goto fail;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_ready(c->query);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannfail:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_warning_errno(r, "Failed to follow search domains: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann c->error_code = r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_ready(c->query);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic void dns_query_stop(DnsQuery *q) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsQueryCandidate *c;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_FOREACH(candidates_by_query, c, q->candidates)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_candidate_stop(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid HerrmannDnsQuery *dns_query_free(DnsQuery *q) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!q)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return NULL;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann while (q->auxiliary_queries)
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann dns_query_free(q->auxiliary_queries);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (q->auxiliary_for) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q->auxiliary_for->n_auxiliary_queries > 0);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->auxiliary_for->n_auxiliary_queries--;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann }
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann while (q->candidates)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_candidate_free(q->candidates);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_question_unref(q->question);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_answer_unref(q->answer);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann dns_search_domain_unref(q->answer_search_domain);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann sd_bus_message_unref(q->request);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann sd_bus_track_unref(q->bus_track);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (q->manager) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_REMOVE(queries, q->manager->dns_queries, q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->manager->n_dns_queries--;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering }
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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 unsigned i;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering assert(m);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering assert(question);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_question_is_valid_for_query(question);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m->n_dns_queries >= QUERIES_MAX)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -EBUSY;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q = new0(DnsQuery, 1);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!q)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->question = dns_question_ref(question);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->ifindex = ifindex;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering q->flags = flags;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering q->answer_family = AF_UNSPEC;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->answer_protocol = _DNS_PROTOCOL_INVALID;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (i = 0; i < question->n_keys; i++) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ char *p;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_resource_key_to_string(question->keys[i], &p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_debug("Looking up RR for %s", p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_PREPEND(queries, m->dns_queries, q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann m->n_dns_queries++;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->manager = m;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (ret)
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering *ret = q;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannint dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(auxiliary_for);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Ensure that that the query is not auxiliary yet, and
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * nothing else is auxiliary to it either */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(!q->auxiliary_for);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(!q->auxiliary_queries);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Ensure that the unit we shall be made auxiliary for isn't
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * auxiliary itself */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(!auxiliary_for->auxiliary_for);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -EAGAIN;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->auxiliary_for = auxiliary_for;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann auxiliary_for->n_auxiliary_queries++;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
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
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 Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->state = state;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_stop(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (q->complete)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->complete(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsQuery *q = userdata;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(s);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
1140e154100f7224fb8bab55ba7fc087409f9d76Lennart Poetteringstatic int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsQueryCandidate *c;
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann int r;
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(s);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_new(&c, q, s);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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 if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann goto fail;
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann if (r > 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* OK, we need a search domain now. Let's find one for this scope */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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. */
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann goto fail;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_query_candidate_setup_transactions(c);
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (r < 0)
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann goto fail;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannfail:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann dns_query_candidate_free(c);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int SYNTHESIZE_IFINDEX(int ifindex) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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 Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (ifindex > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return ifindex;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return LOOPBACK_IFINDEX;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int SYNTHESIZE_FAMILY(uint64_t flags) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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 Herrmann * here. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!(flags & SD_RESOLVED_DNS)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (flags & SD_RESOLVED_LLMNR_IPV4)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return AF_INET;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (flags & SD_RESOLVED_LLMNR_IPV6)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return AF_INET6;
1140e154100f7224fb8bab55ba7fc087409f9d76Lennart Poettering }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann return AF_UNSPEC;
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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. */
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (flags & SD_RESOLVED_DNS)
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann return DNS_PROTOCOL_DNS;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (flags & SD_RESOLVED_LLMNR)
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann return DNS_PROTOCOL_LLMNR;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann return DNS_PROTOCOL_DNS;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann}
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmannstatic int dns_type_to_af(uint16_t t) {
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann switch (t) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann case DNS_TYPE_A:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return AF_INET;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann case DNS_TYPE_AAAA:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return AF_INET6;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann case DNS_TYPE_ANY:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return AF_UNSPEC;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann default:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -EINVAL;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann }
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(key);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_reserve(answer, 2);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (!rr)
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return -ENOMEM;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (r < 0)
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return r;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann }
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
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
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!rr)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann rr->aaaa.in6_addr = in6addr_loopback;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
61adca52f6f0b119e501c523008a454887cdf2b9Lennart Poettering if (!rr)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann rr->ptr.name = strdup(to);
61adca52f6f0b119e501c523008a454887cdf2b9Lennart Poettering if (!rr->ptr.name)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ENOMEM;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return dns_answer_add(*answer, rr, ifindex);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(key);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering assert(answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_reserve(answer, 1);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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 if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int answer_add_addresses_rr(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsAnswer **answer,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *name,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct local_address *addresses,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann unsigned n_addresses) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann unsigned j;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(name);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_reserve(answer, n_addresses);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (j = 0; j < n_addresses; j++) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_add(*answer, rr, addresses[j].ifindex);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int answer_add_addresses_ptr(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DnsAnswer **answer,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *name,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct local_address *addresses,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann unsigned n_addresses,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int af, const union in_addr_union *match) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann unsigned j;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (j = 0; j < n_addresses; j++) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (af != AF_UNSPEC) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (addresses[j].family != af)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (match && !in_addr_equal(af, match, &addresses[j].address))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_reserve(answer, 1);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_add(*answer, rr, addresses[j].ifindex);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ struct local_address *addresses = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int n = 0, af;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(key);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann af = dns_type_to_af(key->type);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (af >= 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (n < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return n;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (n == 0) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering struct local_address buffer[2];
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* If we have no local addresses then use ::1
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering * and 127.0.0.2 as local ones. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (af == AF_INET || af == AF_UNSPEC)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann buffer[n++] = (struct local_address) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .family = AF_INET,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .address.in.s_addr = htobe32(0x7F000002),
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann };
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (af == AF_INET6 || af == AF_UNSPEC)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann buffer[n++] = (struct local_address) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .family = AF_INET6,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann .address.in6 = in6addr_loopback,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann };
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int n, r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(address);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Always map the IPv4 address 127.0.0.2 to the local
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * hostname, in addition to "localhost": */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = dns_answer_reserve(answer, 3);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (n < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return n;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ struct local_address *addresses = NULL;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering int n = 0, af;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(key);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann af = dns_type_to_af(key->type);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (af >= 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (n < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return n;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
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 int n;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(address);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (n < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return n;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann unsigned i;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(q);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(state);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Tries to synthesize localhost RR replies where appropriate */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!IN_SET(*state,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DNS_TRANSACTION_FAILURE,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DNS_TRANSACTION_NO_SERVERS,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DNS_TRANSACTION_TIMEOUT,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann DNS_TRANSACTION_ATTEMPTS_MAX_REACHED))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering for (i = 0; i < q->question->n_keys; i++) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann union in_addr_union address;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *name;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int af;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (q->question->keys[i]->class != DNS_CLASS_IN &&
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann q->question->keys[i]->class != DNS_CLASS_ANY)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (is_localhost(name)) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
} else if (manager_is_own_hostname(q->manager, name)) {
r = synthesize_system_hostname_rr(q, q->question->keys[i], &answer);
if (r < 0)
return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
} else if (is_gateway_hostname(name)) {
r = synthesize_gateway_rr(q, q->question->keys[i], &answer);
if (r < 0)
return log_error_errno(r, "Failed to synthesize gateway 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) {
r = synthesize_localhost_ptr(q, q->question->keys[i], &answer);
if (r < 0)
return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
} else if (dns_name_address(name, &af, &address) > 0) {
r = synthesize_system_hostname_ptr(q, af, &address, &answer);
if (r < 0)
return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
r = synthesize_gateway_ptr(q, af, &address, &answer);
if (r < 0)
return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
}
}
if (!answer)
return 0;
dns_answer_unref(q->answer);
q->answer = answer;
answer = NULL;
q->answer_rcode = DNS_RCODE_SUCCESS;
q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
q->answer_family = SYNTHESIZE_FAMILY(q->flags);
*state = DNS_TRANSACTION_SUCCESS;
return 1;
}
int dns_query_go(DnsQuery *q) {
DnsScopeMatch found = DNS_SCOPE_NO;
DnsScope *s, *first = NULL;
DnsQueryCandidate *c;
const char *name;
int r;
assert(q);
if (q->state != DNS_TRANSACTION_NULL)
return 0;
assert(q->question);
assert(q->question->n_keys > 0);
name = dns_question_first_name(q->question);
LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
DnsScopeMatch match;
match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
if (match < 0)
return match;
if (match == DNS_SCOPE_NO)
continue;
found = match;
if (match == DNS_SCOPE_YES) {
first = s;
break;
} else {
assert(match == DNS_SCOPE_MAYBE);
if (!first)
first = s;
}
}
if (found == DNS_SCOPE_NO) {
DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
dns_query_synthesize_reply(q, &state);
dns_query_complete(q, state);
return 1;
}
r = dns_query_add_candidate(q, first);
if (r < 0)
goto fail;
LIST_FOREACH(scopes, s, first->scopes_next) {
DnsScopeMatch match;
match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
if (match < 0)
goto fail;
if (match != found)
continue;
r = dns_query_add_candidate(q, s);
if (r < 0)
goto fail;
}
q->answer = dns_answer_unref(q->answer);
q->answer_rcode = 0;
q->answer_family = AF_UNSPEC;
q->answer_protocol = _DNS_PROTOCOL_INVALID;
r = sd_event_add_time(
q->manager->event,
&q->timeout_event_source,
clock_boottime_or_monotonic(),
now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
on_query_timeout, q);
if (r < 0)
goto fail;
q->state = DNS_TRANSACTION_PENDING;
q->block_ready++;
/* Start the transactions */
LIST_FOREACH(candidates_by_query, c, q->candidates) {
r = dns_query_candidate_go(c);
if (r < 0) {
q->block_ready--;
goto fail;
}
}
q->block_ready--;
dns_query_ready(q);
return 1;
fail:
dns_query_stop(q);
return r;
}
static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
DnsTransaction *t;
Iterator i;
assert(q);
if (!c) {
dns_query_synthesize_reply(q, &state);
dns_query_complete(q, state);
return;
}
SET_FOREACH(t, c->transactions, i) {
switch (t->state) {
case DNS_TRANSACTION_SUCCESS: {
/* We found a successfuly reply, merge it into the answer */
DnsAnswer *merged, *a;
if (t->received) {
q->answer_rcode = DNS_PACKET_RCODE(t->received);
a = t->received->answer;
} else {
q->answer_rcode = t->cached_rcode;
a = t->cached;
}
merged = dns_answer_merge(q->answer, a);
if (!merged) {
dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
return;
}
dns_answer_unref(q->answer);
q->answer = merged;
state = DNS_TRANSACTION_SUCCESS;
break;
}
case DNS_TRANSACTION_PENDING:
case DNS_TRANSACTION_NULL:
case DNS_TRANSACTION_ABORTED:
/* Ignore transactions that didn't complete */
continue;
default:
/* Any kind of failure? Store the data away,
* if there's nothing stored yet. */
if (state != DNS_TRANSACTION_SUCCESS) {
dns_answer_unref(q->answer);
if (t->received) {
q->answer = dns_answer_ref(t->received->answer);
q->answer_rcode = DNS_PACKET_RCODE(t->received);
} else {
q->answer = dns_answer_ref(t->cached);
q->answer_rcode = t->cached_rcode;
}
state = t->state;
}
break;
}
}
q->answer_protocol = c->scope->protocol;
q->answer_family = c->scope->family;
dns_search_domain_unref(q->answer_search_domain);
q->answer_search_domain = dns_search_domain_ref(c->search_domain);
dns_query_synthesize_reply(q, &state);
dns_query_complete(q, state);
}
void dns_query_ready(DnsQuery *q) {
DnsQueryCandidate *bad = NULL, *c;
bool pending = false;
assert(q);
assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
/* Note that this call might invalidate the query. Callers
* should hence not attempt to access the query or transaction
* after calling this function, unless the block_ready
* counter was explicitly bumped before doing so. */
if (q->block_ready > 0)
return;
LIST_FOREACH(candidates_by_query, c, q->candidates) {
DnsTransactionState state;
state = dns_query_candidate_state(c);
switch (state) {
case DNS_TRANSACTION_SUCCESS:
/* One of the transactions is successful,
* let's use it, and copy its data out */
dns_query_accept(q, c);
return;
case DNS_TRANSACTION_PENDING:
case DNS_TRANSACTION_NULL:
/* One of the transactions is still going on, let's maybe wait for it */
pending = true;
break;
default:
/* Any kind of failure */
bad = c;
break;
}
}
if (pending)
return;
dns_query_accept(q, bad);
}
static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) {
_cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
int r;
assert(q);
q->n_cname_redirects ++;
if (q->n_cname_redirects > CNAME_MAX)
return -ELOOP;
r = dns_question_cname_redirect(q->question, cname, &nq);
if (r < 0)
return r;
dns_question_unref(q->question);
q->question = nq;
nq = NULL;
dns_query_stop(q);
q->state = DNS_TRANSACTION_NULL;
return 0;
}
int dns_query_process_cname(DnsQuery *q) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL;
DnsResourceRecord *rr;
int r;
assert(q);
if (q->state != DNS_TRANSACTION_SUCCESS)
return 0;
DNS_ANSWER_FOREACH(rr, q->answer) {
r = dns_question_matches_rr(q->question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
if (r < 0)
return r;
if (r > 0)
return 0; /* The answer matches directly, no need to follow cnames */
r = dns_question_matches_cname(q->question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
if (r < 0)
return r;
if (r > 0 && !cname)
cname = dns_resource_record_ref(rr);
}
if (!cname)
return 0; /* No cname to follow */
if (q->flags & SD_RESOLVED_NO_CNAME)
return -ELOOP;
/* OK, let's actually follow the CNAME */
r = dns_query_cname_redirect(q, cname);
if (r < 0)
return r;
/* Let's see if the answer can already answer the new
* redirected question */
DNS_ANSWER_FOREACH(rr, q->answer) {
r = dns_question_matches_rr(q->question, rr, NULL);
if (r < 0)
return r;
if (r > 0)
return 0; /* It can answer it, yay! */
}
/* OK, it cannot, let's begin with the new query */
r = dns_query_go(q);
if (r < 0)
return r;
return 1; /* We return > 0, if we restarted the query for a new cname */
}
static int on_bus_track(sd_bus_track *t, void *userdata) {
DnsQuery *q = userdata;
assert(t);
assert(q);
log_debug("Client of active query vanished, aborting query.");
dns_query_complete(q, DNS_TRANSACTION_ABORTED);
return 0;
}
int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
int r;
assert(q);
assert(m);
if (!q->bus_track) {
r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q);
if (r < 0)
return r;
}
r = sd_bus_track_add_sender(q->bus_track, m);
if (r < 0)
return r;
return 0;
}