1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 typedef struct DnsQueryCandidate DnsQueryCandidate
;
10 typedef struct DnsQuery DnsQuery
;
11 typedef struct DnsStubListenerExtra DnsStubListenerExtra
;
13 #include "resolved-dns-answer.h"
14 #include "resolved-dns-question.h"
15 #include "resolved-dns-search-domain.h"
16 #include "resolved-dns-transaction.h"
18 struct DnsQueryCandidate
{
25 DnsSearchDomain
*search_domain
;
29 LIST_FIELDS(DnsQueryCandidate
, candidates_by_query
);
30 LIST_FIELDS(DnsQueryCandidate
, candidates_by_scope
);
36 /* When resolving a service, we first create a TXT+SRV query, and then for the hostnames we discover
37 * auxiliary A+AAAA queries. This pointer always points from the auxiliary queries back to the
39 DnsQuery
*auxiliary_for
;
40 LIST_HEAD(DnsQuery
, auxiliary_queries
);
41 unsigned n_auxiliary_queries
;
44 /* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note
45 * that even on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names
46 * (in contrast to their domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference
47 * between these two fields is mostly relevant only for explicit *hostname* lookups as well as the
48 * domain suffixes of service lookups.
50 * Note that questions may consist of multiple RR keys at once, but they must be for the same domain
51 * name. This is used for A+AAAA and TXT+SRV lookups: we'll allocate a single DnsQuery object for
52 * them instead of two separate ones. That allows us minor optimizations with response handling:
53 * CNAME/DNAMEs of the first reply we get can already be used to follow the CNAME/DNAME chain for
54 * both, and we can take benefit of server replies that oftentimes put A responses into AAAA queries
55 * and vice versa (in the additional section). */
56 DnsQuestion
*question_idna
;
57 DnsQuestion
*question_utf8
;
59 /* If this is not a question by ourselves, but a "bypass" request, we propagate the original packet
60 * here, and use that instead. */
61 DnsPacket
*question_bypass
;
66 DnsTransactionState state
;
67 unsigned n_cname_redirects
;
69 LIST_HEAD(DnsQueryCandidate
, candidates
);
70 sd_event_source
*timeout_event_source
;
75 DnssecResult answer_dnssec_result
;
76 uint64_t answer_query_flags
;
77 DnsProtocol answer_protocol
;
79 DnsSearchDomain
*answer_search_domain
;
80 int answer_errno
; /* if state is DNS_TRANSACTION_ERRNO */
81 bool previous_redirect_unauthenticated
;
82 bool previous_redirect_non_confidential
;
83 bool previous_redirect_non_synthetic
;
84 DnsPacket
*answer_full_packet
;
86 /* Bus + Varlink client information */
87 sd_bus_message
*bus_request
;
88 Varlink
*varlink_request
;
90 bool request_address_valid
;
91 union in_addr_union request_address
;
92 unsigned block_all_complete
;
93 char *request_address_string
;
95 /* DNS stub information */
96 DnsPacket
*request_packet
;
97 DnsStream
*request_stream
;
98 DnsAnswer
*reply_answer
;
99 DnsAnswer
*reply_authoritative
;
100 DnsAnswer
*reply_additional
;
101 DnsStubListenerExtra
*stub_listener_extra
;
103 /* Completion callback */
104 void (*complete
)(DnsQuery
* q
);
105 unsigned block_ready
;
107 sd_bus_track
*bus_track
;
109 LIST_FIELDS(DnsQuery
, queries
);
110 LIST_FIELDS(DnsQuery
, auxiliary_queries
);
119 DnsQueryCandidate
* dns_query_candidate_ref(DnsQueryCandidate
*);
120 DnsQueryCandidate
* dns_query_candidate_unref(DnsQueryCandidate
*);
121 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate
*, dns_query_candidate_unref
);
123 void dns_query_candidate_notify(DnsQueryCandidate
*c
);
125 int dns_query_new(Manager
*m
, DnsQuery
**q
, DnsQuestion
*question_utf8
, DnsQuestion
*question_idna
, DnsPacket
*question_bypass
, int family
, uint64_t flags
);
126 DnsQuery
*dns_query_free(DnsQuery
*q
);
128 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
);
130 int dns_query_go(DnsQuery
*q
);
131 void dns_query_ready(DnsQuery
*q
);
133 int dns_query_process_cname_one(DnsQuery
*q
);
134 int dns_query_process_cname_many(DnsQuery
*q
);
136 void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
);
138 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
);
140 const char *dns_query_string(DnsQuery
*q
);
142 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery
*, dns_query_free
);
144 bool dns_query_fully_authenticated(DnsQuery
*q
);
145 bool dns_query_fully_confidential(DnsQuery
*q
);
146 bool dns_query_fully_authoritative(DnsQuery
*q
);
148 static inline uint64_t dns_query_reply_flags_make(DnsQuery
*q
) {
151 return SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
,
153 dns_query_fully_authenticated(q
),
154 dns_query_fully_confidential(q
)) |
155 (q
->answer_query_flags
& (SD_RESOLVED_FROM_MASK
|SD_RESOLVED_SYNTHETIC
));
158 #define CNAME_REDIRECT_MAX 16