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 /* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note
37 * that even on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names
38 * (in contrast to their domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference
39 * between these two fields is mostly relevant only for explicit *hostname* lookups as well as the
40 * domain suffixes of service lookups.
42 * Note that questions may consist of multiple RR keys at once, but they must be for the same domain
43 * name. This is used for A+AAAA and TXT+SRV lookups: we'll allocate a single DnsQuery object for
44 * them instead of two separate ones. That allows us minor optimizations with response handling:
45 * CNAME/DNAMEs of the first reply we get can already be used to follow the CNAME/DNAME chain for
46 * both, and we can take benefit of server replies that oftentimes put A responses into AAAA queries
47 * and vice versa (in the additional section). */
48 DnsQuestion
*question_idna
;
49 DnsQuestion
*question_utf8
;
51 /* If this is not a question by ourselves, but a "bypass" request, we propagate the original packet
52 * here, and use that instead. */
53 DnsPacket
*question_bypass
;
58 /* When resolving a service, we first create a TXT+SRV query, and then for the hostnames we discover
59 * auxiliary A+AAAA queries. This pointer always points from the auxiliary queries back to the
62 DnsQuery
*auxiliary_for
;
63 LIST_HEAD(DnsQuery
, auxiliary_queries
);
65 LIST_HEAD(DnsQueryCandidate
, candidates
);
66 sd_event_source
*timeout_event_source
;
71 DnssecResult answer_dnssec_result
;
72 uint64_t answer_query_flags
;
73 DnsProtocol answer_protocol
;
75 DnsPacket
*answer_full_packet
;
76 DnsSearchDomain
*answer_search_domain
;
78 DnsTransactionState state
;
79 int answer_errno
; /* if state is DNS_TRANSACTION_ERRNO */
83 uint8_t n_auxiliary_queries
;
84 uint8_t n_cname_redirects
;
86 bool previous_redirect_unauthenticated
:1;
87 bool previous_redirect_non_confidential
:1;
88 bool previous_redirect_non_synthetic
:1;
89 bool request_address_valid
:1;
91 /* Bus + Varlink client information */
92 sd_bus_message
*bus_request
;
93 Varlink
*varlink_request
;
95 union in_addr_union request_address
;
96 unsigned block_all_complete
;
97 char *request_address_string
;
100 /* DNS stub information */
101 DnsPacket
*request_packet
;
102 DnsStream
*request_stream
;
103 DnsAnswer
*reply_answer
;
104 DnsAnswer
*reply_authoritative
;
105 DnsAnswer
*reply_additional
;
106 DnsStubListenerExtra
*stub_listener_extra
;
108 /* Completion callback */
109 void (*complete
)(DnsQuery
* q
);
111 sd_bus_track
*bus_track
;
113 LIST_FIELDS(DnsQuery
, queries
);
114 LIST_FIELDS(DnsQuery
, auxiliary_queries
);
116 /* Note: fields should be ordered to minimize alignment gaps. Use pahole! */
125 DnsQueryCandidate
* dns_query_candidate_ref(DnsQueryCandidate
*);
126 DnsQueryCandidate
* dns_query_candidate_unref(DnsQueryCandidate
*);
127 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate
*, dns_query_candidate_unref
);
129 void dns_query_candidate_notify(DnsQueryCandidate
*c
);
131 int dns_query_new(Manager
*m
, DnsQuery
**q
, DnsQuestion
*question_utf8
, DnsQuestion
*question_idna
, DnsPacket
*question_bypass
, int family
, uint64_t flags
);
132 DnsQuery
*dns_query_free(DnsQuery
*q
);
134 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
);
136 int dns_query_go(DnsQuery
*q
);
137 void dns_query_ready(DnsQuery
*q
);
139 int dns_query_process_cname_one(DnsQuery
*q
);
140 int dns_query_process_cname_many(DnsQuery
*q
);
142 void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
);
144 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
);
146 const char *dns_query_string(DnsQuery
*q
);
148 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery
*, dns_query_free
);
150 bool dns_query_fully_authenticated(DnsQuery
*q
);
151 bool dns_query_fully_confidential(DnsQuery
*q
);
152 bool dns_query_fully_authoritative(DnsQuery
*q
);
154 static inline uint64_t dns_query_reply_flags_make(DnsQuery
*q
) {
157 return SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
,
159 dns_query_fully_authenticated(q
),
160 dns_query_fully_confidential(q
)) |
161 (q
->answer_query_flags
& (SD_RESOLVED_FROM_MASK
|SD_RESOLVED_SYNTHETIC
));