]>
Commit | Line | Data |
---|---|---|
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ | |
2 | #pragma once | |
3 | ||
4 | #include "in-addr-util.h" | |
5 | #include "list.h" | |
6 | #include "resolved-dns-packet.h" | |
7 | #include "resolved-dns-transaction.h" | |
8 | #include "resolved-forward.h" | |
9 | ||
10 | typedef struct DnsQueryCandidate { | |
11 | unsigned n_ref; | |
12 | int error_code; | |
13 | uint64_t generation; | |
14 | ||
15 | DnsQuery *query; | |
16 | DnsScope *scope; | |
17 | ||
18 | DnsSearchDomain *search_domain; | |
19 | ||
20 | Set *transactions; | |
21 | sd_event_source *timeout_event_source; | |
22 | ||
23 | LIST_FIELDS(DnsQueryCandidate, candidates_by_query); | |
24 | LIST_FIELDS(DnsQueryCandidate, candidates_by_scope); | |
25 | } DnsQueryCandidate; | |
26 | ||
27 | typedef struct DnsQuery { | |
28 | Manager *manager; | |
29 | ||
30 | /* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note | |
31 | * that even on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names | |
32 | * (in contrast to their domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference | |
33 | * between these two fields is mostly relevant only for explicit *hostname* lookups as well as the | |
34 | * domain suffixes of service lookups. | |
35 | * | |
36 | * Note that questions may consist of multiple RR keys at once, but they must be for the same domain | |
37 | * name. This is used for A+AAAA and TXT+SRV lookups: we'll allocate a single DnsQuery object for | |
38 | * them instead of two separate ones. That allows us minor optimizations with response handling: | |
39 | * CNAME/DNAMEs of the first reply we get can already be used to follow the CNAME/DNAME chain for | |
40 | * both, and we can take benefit of server replies that oftentimes put A responses into AAAA queries | |
41 | * and vice versa (in the additional section). */ | |
42 | DnsQuestion *question_idna; | |
43 | DnsQuestion *question_utf8; | |
44 | ||
45 | /* If this is not a question by ourselves, but a "bypass" request, we propagate the original packet | |
46 | * here, and use that instead. */ | |
47 | DnsPacket *question_bypass; | |
48 | ||
49 | /* When we follow a CNAME redirect, we save the original question here, for informational/monitoring | |
50 | * purposes. We'll keep adding to this whenever we go one step in the redirect, so that in the end | |
51 | * this will contain the complete set of CNAME questions. */ | |
52 | DnsQuestion *collected_questions; | |
53 | ||
54 | uint64_t flags; | |
55 | int ifindex; | |
56 | ||
57 | /* When resolving a service, we first create a TXT+SRV query, and then for the hostnames we discover | |
58 | * auxiliary A+AAAA queries. This pointer always points from the auxiliary queries back to the | |
59 | * TXT+SRV query. */ | |
60 | int auxiliary_result; | |
61 | DnsQuery *auxiliary_for; | |
62 | LIST_HEAD(DnsQuery, auxiliary_queries); | |
63 | ||
64 | LIST_HEAD(DnsQueryCandidate, candidates); | |
65 | sd_event_source *timeout_event_source; | |
66 | ||
67 | /* Discovered data */ | |
68 | DnsAnswer *answer; | |
69 | int answer_rcode; | |
70 | int answer_ede_rcode; | |
71 | char *answer_ede_msg; | |
72 | DnssecResult answer_dnssec_result; | |
73 | uint64_t answer_query_flags; | |
74 | DnsProtocol answer_protocol; | |
75 | int answer_family; | |
76 | DnsPacket *answer_full_packet; | |
77 | DnsSearchDomain *answer_search_domain; | |
78 | ||
79 | DnsTransactionState state; | |
80 | int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */ | |
81 | ||
82 | unsigned block_ready; | |
83 | ||
84 | uint8_t n_auxiliary_queries; | |
85 | uint8_t n_cname_redirects; | |
86 | ||
87 | bool previous_redirect_unauthenticated:1; | |
88 | bool previous_redirect_non_confidential:1; | |
89 | bool previous_redirect_non_synthetic:1; | |
90 | bool request_address_valid:1; | |
91 | ||
92 | /* Bus + Varlink client information */ | |
93 | sd_bus_message *bus_request; | |
94 | sd_varlink *varlink_request; | |
95 | int request_family; | |
96 | union in_addr_union request_address; | |
97 | unsigned block_all_complete; | |
98 | char *request_address_string; | |
99 | ||
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; | |
107 | ||
108 | /* Completion callback */ | |
109 | void (*complete)(DnsQuery* q); | |
110 | ||
111 | sd_bus_track *bus_track; | |
112 | ||
113 | LIST_FIELDS(DnsQuery, queries); | |
114 | LIST_FIELDS(DnsQuery, auxiliary_queries); | |
115 | ||
116 | /* Note: fields should be ordered to minimize alignment gaps. Use pahole! */ | |
117 | } DnsQuery; | |
118 | ||
119 | enum { | |
120 | DNS_QUERY_MATCH, | |
121 | DNS_QUERY_NOMATCH, | |
122 | DNS_QUERY_CNAME, | |
123 | }; | |
124 | ||
125 | DnsQueryCandidate* dns_query_candidate_ref(DnsQueryCandidate*); | |
126 | DnsQueryCandidate* dns_query_candidate_unref(DnsQueryCandidate*); | |
127 | DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_unref); | |
128 | ||
129 | void dns_query_candidate_notify(DnsQueryCandidate *c); | |
130 | ||
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); | |
133 | ||
134 | int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for); | |
135 | ||
136 | int dns_query_go(DnsQuery *q); | |
137 | void dns_query_ready(DnsQuery *q); | |
138 | ||
139 | int dns_query_process_cname_one(DnsQuery *q); | |
140 | int dns_query_process_cname_many(DnsQuery *q); | |
141 | ||
142 | void dns_query_complete(DnsQuery *q, DnsTransactionState state); | |
143 | ||
144 | DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol); | |
145 | ||
146 | const char* dns_query_string(DnsQuery *q); | |
147 | ||
148 | DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free); | |
149 | ||
150 | bool dns_query_fully_authenticated(DnsQuery *q); | |
151 | bool dns_query_fully_confidential(DnsQuery *q); | |
152 | bool dns_query_fully_authoritative(DnsQuery *q); | |
153 | ||
154 | int validate_and_mangle_query_flags(Manager *manager, uint64_t *flags, const char *name, uint64_t ok); | |
155 | ||
156 | uint64_t dns_query_reply_flags_make(DnsQuery *q); |