resolved-dns-query.c revision d634711b261dc72bb48765e8574ba43d455e82ec
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2014 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering/* How long to wait for the query in total */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering while ((t = set_steal_first(q->transactions))) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen LIST_REMOVE(queries, q->manager->dns_queries, q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_query_freep) DnsQuery *q = NULL;
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering q->question = dns_question_ref(question);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_resource_key_to_string(question->keys[i], &p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_PREPEND(queries, m->dns_queries, q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Note that this call might invalidate the query. Callers
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * should hence not attempt to access the query or transaction
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * after calling this function. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = set_ensure_allocated(&q->transactions, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering t = dns_scope_find_transaction(s, key, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = set_ensure_allocated(&t->queries, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Create one transaction per question key */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < q->question->n_keys; i++) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_query_add_transaction(q, s, q->question->keys[i]);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* When the caller asked for resolving on a specific
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * interface, we synthesize the answer for that
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * interface. However, if nothing specific was claimed and we
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø * only return localhost RRs, we synthesize the answer for
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen * localhost. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Picks an address family depending on set flags. This is
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * purely for synthesized answers, where the family we return
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen * for the reply should match what was requested in the
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * question, even though we are synthesizing the answer
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Similar as SYNTHESIZE_FAMILY() but does this for the
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen * protocol. If resolving via DNS was requested, we claim it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * was DNS. Similar, if nothing specific was
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * requested. However, if only resolving via LLMNR was
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * requested we return that. */
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return dns_answer_add(*answer, rr, ifindex);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_answer_reserve(answer, n_addresses);
422baca0f230913158078fddf884e06c8c64a316Lennart Poettering for (j = 0; j < n_addresses; j++) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_answer_add(*answer, rr, addresses[j].ifindex);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int af, const union in_addr_union *match) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering for (j = 0; j < n_addresses; j++) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (match && !in_addr_equal(af, match, &addresses[j].address))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_answer_add(*answer, rr, addresses[j].ifindex);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering /* If we have no local addresses then use ::1
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering * and 127.0.0.2 as local ones. */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering .address.in.s_addr = htobe32(0x7F000002),
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poetteringstatic int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering /* Always map the IPv4 address 127.0.0.2 to the local
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering * hostname, in addition to "localhost": */
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenstatic int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringstatic int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack /* Tries to synthesize localhost RR replies where appropriate */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < q->question->n_keys; i++) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (q->question->keys[i]->class != DNS_CLASS_IN &&
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->question->keys[i]->class != DNS_CLASS_ANY)
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering } else if (manager_is_own_hostname(q->manager, name)) {
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering r = synthesize_system_hostname_rr(q, q->question->keys[i], &answer);
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering r = synthesize_gateway_rr(q, q->question->keys[i], &answer);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering 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) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = synthesize_localhost_ptr(q, q->question->keys[i], &answer);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else if (dns_name_address(name, &af, &address) > 0) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = synthesize_system_hostname_ptr(q, af, &address, &answer);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering r = synthesize_gateway_ptr(q, af, &address, &answer);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->answer_family = SYNTHESIZE_FAMILY(q->flags);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_query_add_transaction_split(q, first);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering LIST_FOREACH(scopes, s, first->scopes_next) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_query_add_transaction_split(q, s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer_protocol = _DNS_PROTOCOL_INVALID;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* Start the transactions that are not started yet */
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Note that this call might invalidate the query. Callers
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * should hence not attempt to access the query or transaction
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * after calling this function, unless the block_ready
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * counter was explicitly bumped before doing so. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we found a successful answer, ignore all answers from other scopes */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (state == DNS_TRANSACTION_SUCCESS && t->scope != scope)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* One of the transactions is still going on, let's maybe wait for it */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* One of the transactions is successful, let's use
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * it, and copy its data out */
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen /* One of the transactions has failed, let's see
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen * whether we find anything better, but if not, return
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen * its response data */
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (state != DNS_TRANSACTION_SUCCESS && t->state == DNS_TRANSACTION_FAILURE) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (state == DNS_TRANSACTION_NO_SERVERS && t->state != DNS_TRANSACTION_NO_SERVERS)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If so far we weren't successful, and there's
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * something still pending, then wait for it */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we already were successful, then only wait for
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * other transactions on the same scope to finish. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (t->scope == scope && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IN_SET(state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer_protocol = scope ? scope->protocol : _DNS_PROTOCOL_INVALID;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer_family = scope ? scope->family : AF_UNSPEC;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Try to synthesize a reply if we couldn't resolve something. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_query_cname_redirect(DnsQuery *q, const char *name) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_question_cname_redirect(q->question, name, &nq);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int on_bus_track(sd_bus_track *t, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Client of active query vanished, aborting query.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_query_complete(q, DNS_TRANSACTION_ABORTED);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q);