]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-query.h
Merge pull request #18886 from anitazha/shutdownconsole
[thirdparty/systemd.git] / src / resolve / resolved-dns-query.h
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3
4 #include "sd-bus.h"
5
6 #include "set.h"
7 #include "varlink.h"
8
9 typedef struct DnsQueryCandidate DnsQueryCandidate;
10 typedef struct DnsQuery DnsQuery;
11 typedef struct DnsStubListenerExtra DnsStubListenerExtra;
12
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"
17
18 struct DnsQueryCandidate {
19 unsigned n_ref;
20 int error_code;
21
22 DnsQuery *query;
23 DnsScope *scope;
24
25 DnsSearchDomain *search_domain;
26
27 Set *transactions;
28
29 LIST_FIELDS(DnsQueryCandidate, candidates_by_query);
30 LIST_FIELDS(DnsQueryCandidate, candidates_by_scope);
31 };
32
33 struct DnsQuery {
34 Manager *manager;
35
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
38 * TXT+SRV query. */
39 DnsQuery *auxiliary_for;
40 LIST_HEAD(DnsQuery, auxiliary_queries);
41 unsigned n_auxiliary_queries;
42 int auxiliary_result;
43
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.
49 *
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;
58
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;
62
63 uint64_t flags;
64 int ifindex;
65
66 DnsTransactionState state;
67 unsigned n_cname_redirects;
68
69 LIST_HEAD(DnsQueryCandidate, candidates);
70 sd_event_source *timeout_event_source;
71
72 /* Discovered data */
73 DnsAnswer *answer;
74 int answer_rcode;
75 DnssecResult answer_dnssec_result;
76 uint64_t answer_query_flags;
77 DnsProtocol answer_protocol;
78 int answer_family;
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;
85
86 /* Bus + Varlink client information */
87 sd_bus_message *bus_request;
88 Varlink *varlink_request;
89 int request_family;
90 bool request_address_valid;
91 union in_addr_union request_address;
92 unsigned block_all_complete;
93 char *request_address_string;
94
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;
102
103 /* Completion callback */
104 void (*complete)(DnsQuery* q);
105 unsigned block_ready;
106
107 sd_bus_track *bus_track;
108
109 LIST_FIELDS(DnsQuery, queries);
110 LIST_FIELDS(DnsQuery, auxiliary_queries);
111 };
112
113 enum {
114 DNS_QUERY_MATCH,
115 DNS_QUERY_NOMATCH,
116 DNS_QUERY_CNAME,
117 };
118
119 DnsQueryCandidate* dns_query_candidate_ref(DnsQueryCandidate*);
120 DnsQueryCandidate* dns_query_candidate_unref(DnsQueryCandidate*);
121 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_unref);
122
123 void dns_query_candidate_notify(DnsQueryCandidate *c);
124
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);
127
128 int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for);
129
130 int dns_query_go(DnsQuery *q);
131 void dns_query_ready(DnsQuery *q);
132
133 int dns_query_process_cname_one(DnsQuery *q);
134 int dns_query_process_cname_many(DnsQuery *q);
135
136 void dns_query_complete(DnsQuery *q, DnsTransactionState state);
137
138 DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol);
139
140 const char *dns_query_string(DnsQuery *q);
141
142 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free);
143
144 bool dns_query_fully_authenticated(DnsQuery *q);
145 bool dns_query_fully_confidential(DnsQuery *q);
146 bool dns_query_fully_authoritative(DnsQuery *q);
147
148 static inline uint64_t dns_query_reply_flags_make(DnsQuery *q) {
149 assert(q);
150
151 return SD_RESOLVED_FLAGS_MAKE(q->answer_protocol,
152 q->answer_family,
153 dns_query_fully_authenticated(q),
154 dns_query_fully_confidential(q)) |
155 (q->answer_query_flags & (SD_RESOLVED_FROM_MASK|SD_RESOLVED_SYNTHETIC));
156 }
157
158 #define CNAME_REDIRECT_MAX 16