1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 #ifndef DNS_UDP_H
36 #define DNS_UDP_H
37
38 #include <dnscore/host_address.h>
39 #include <dnscore/message.h>
40 #include <dnscore/mutex.h>
41 #include <dnscore/async.h>
42
43 // error codes
44
45 #define DNS_UDP_TIMEOUT ((s32)0x81000001)
46 #define DNS_UDP_INTERNAL ((s32)0x81000002)
47 #define DNS_UDP_CANCEL ((s32)0x81000003)
48
49 //
50
51 #define DNS_UDP_TIMEOUT_US 3000000 // 3s
52
53 #define DNS_UDP_TIMEOUT_US_MIN 1000000 // 1s
54 #define DNS_UDP_TIMEOUT_US_MAX 3600000000// 1h
55
56 #define DNS_UDP_SEND_RATE 1000 // 1000 queries/s
57 #define DNS_UDP_SEND_BANDWIDTH 1000000 // 1MB/s
58 #define DNS_UDP_RECV_BANDWIDTH 1000000 // 1MB/s
59
60 #define DNS_UDP_SEND_RATE_MIN 1 // q/s
61 #define DNS_UDP_SEND_RATE_MAX 1000000 // q/s
62
63 #define DNS_UDP_SEND_BANDWIDTH_MIN 512 // 512B/s
64 #define DNS_UDP_SEND_BANDWIDTH_MAX 100000000 // 100MB/s
65
66 #define DNS_UDP_RECV_BANDWIDTH_MIN 512 // 512B/s
67 #define DNS_UDP_RECV_BANDWIDTH_MAX 100000000 // 100MB/s
68
69 #define DNS_UDP_SEND_QUEUE 200000 // 200000 messages
70
71 #define DNS_UDP_SEND_QUEUE_MIN 1
72 #define DNS_UDP_SEND_QUEUE_MAX 0x1000000 // 16.7M messages
73
74 #define DNS_UDP_PORT_COUNT 256 // A.K.A workers
75 #define DNS_UDP_PORT_COUNT_MIN 1
76 #define DNS_UDP_PORT_COUNT_MAX 4000
77
78 #define DNS_UDP_RETRY_COUNT 2 // tries after the first failure
79 #define DNS_UDP_RETRY_COUNT_MIN 0
80 #define DNS_UDP_RETRY_COUNT_MAX 16
81
82 #define DNS_UDP_PER_DNS_RATE 5 // packets per second
83 #define DNS_UDP_PER_DNS_RATE_MIN 1
84 #define DNS_UDP_PER_DNS_RATE_MAX 65536
85
86 #define DNS_UDP_PER_DNS_BANDWIDTH 4096 // bytes per second
87 #define DNS_UDP_PER_DNS_BANDWIDTH_MIN 512
88 #define DNS_UDP_PER_DNS_BANDWIDTH_MAX 65536
89
90 #define DNS_UDP_PER_DNS_FREQ_MIN 10000 // us between two queries
91 #define DNS_UDP_PER_DNS_FREQ_MIN_MIN 0
92 #define DNS_UDP_PER_DNS_FREQ_MIN_MAX 1000000
93
94 #define DNS_UDP_READ_BUFFER_COUNT 4096
95 #define DNS_UDP_READ_BUFFER_COUNT_MIN 1
96 #define DNS_UDP_READ_BUFFER_COUNT_MAX 8192
97
98 #define DNS_UDP_TCP_THREAD_POOL_SIZE 1
99 #define DNS_UDP_TCP_THREAD_POOL_MIN 1
100 #define DNS_UDP_TCP_THREAD_POOL_MAX 64
101
102 #define DNS_UDP_TCP_FALLBACK_ON_TIMEOUT 0
103
104 #define DNS_UDP_CALLBACK_THREAD_COUNT 4
105 #define DNS_UDP_CALLBACK_THREAD_COUNT_MIN 1
106 #define DNS_UDP_CALLBACK_THREAD_COUNT_MAX 8
107
108 #define DNS_UDP_CALLBACK_QUEUE_SIZE 0x100000
109 #define DNS_UDP_CALLBACK_QUEUE_SIZE_MIN 0x1000
110 #define DNS_UDP_CALLBACK_QUEUE_SIZE_MAX 0x1000000
111
112 #define DNS_SIMPLE_MESSAGE_HAS_WAIT_COND 0
113
114 #define DNS_SIMPLE_MESSAGE_FLAGS_DNSSEC MESSAGE_EDNS0_DNSSEC
115
116 #define DNS_SIMPLE_MESSAGE_STATUS_QUEUED 0x01
117 #define DNS_SIMPLE_MESSAGE_STATUS_COLLECTED 0x02
118 #define DNS_SIMPLE_MESSAGE_STATUS_SENT 0x04
119 #define DNS_SIMPLE_MESSAGE_STATUS_AGGREGATED 0x08
120 #define DNS_SIMPLE_MESSAGE_STATUS_RECEIVED 0x10
121 #define DNS_SIMPLE_MESSAGE_STATUS_TIMEDOUT 0x20
122 #define DNS_SIMPLE_MESSAGE_STATUS_FAILURE 0x40
123 #define DNS_SIMPLE_MESSAGE_STATUS_INVALID 0x80
124
125 struct dns_udp_settings_s
126 {
127 s64 timeout;
128 u32 send_rate;
129 u32 send_bandwidth;
130 u32 recv_bandwidth;
131 u32 queue_size;
132 u32 port_count;
133 u32 retry_count;
134
135 u32 per_dns_rate;
136 u32 per_dns_bandwidth;
137 u32 per_dns_freq_min;
138
139 u32 udp_read_buffer_count;
140
141 u32 callback_queue_size;
142 u8 callback_thread_count;
143
144 u8 tcp_thread_pool_size;
145 bool tcp_fallback_on_timeout;
146
147
148
149 };
150
151 typedef struct dns_udp_settings_s dns_udp_settings_s;
152
153 // reference count common to all dns_simple_message (aggregation of answer for same query)
154
155 struct dns_simple_message_async_node_s
156 {
157 struct dns_simple_message_async_node_s *next;
158 async_message_s *async;
159 };
160
161 typedef struct dns_simple_message_async_node_s dns_simple_message_async_node_s;
162
163 /*
164 * This is basically a DNS query descriptor (retries and all)
165 */
166
167 struct dns_simple_message_s
168 {
169 host_address *name_server;
170
171 message_data *answer; // answer, can be shared
172
173 dns_simple_message_async_node_s async_node;
174 volatile s64 queued_time_us;
175 volatile s64 sent_time_us;
176 volatile s64 received_time_us;
177
178 smp_int rc; // number of references for this message
179 group_mutex_t mtx;
180 volatile thread_t owner;
181
182 int sender_socket; // used so a repeated message will be sent from the same address:port
183 u32 worker_index; // seems to be only useful to get the priority queue index
184 u16 qtype;
185 u16 qclass;
186 u16 flags;
187 u16 source_port; // seems useless
188 u16 dns_id;
189 s8 retries_left;
190 volatile u8 status;
191 u8 recurse:1,tcp:1,tcp_used:1,tcp_replied:1;
192 //bool recurse;
193 //bool tcp; // try TCP
194 u8 fqdn[MAX_DOMAIN_LENGTH];
195 };
196
197 typedef struct dns_simple_message_s dns_simple_message_s;
198
199 /**
200 * This needs to be called before dns_udp_handler_init() or some settings will not be taken
201 * into account
202 *
203 * @param settings that will be used by the dns_udp handler
204 */
205
206 void dns_udp_handler_configure(const dns_udp_settings_s *settings);
207 void dns_udp_handler_host_limit_set(const host_address* name_server,
208 u32 rate,
209 u32 bandwidth,
210 u32 freq_min);
211 int dns_udp_handler_init();
212 int dns_udp_handler_start();
213 int dns_udp_handler_stop();
214 int dns_udp_handler_finalize();
215
216 /**
217 * Cancels all pending queries.
218 * Their handlers will be called with the error message DNS_UDP_CANCEL
219 * The purpose is cleaning up before shutdown.
220 */
221
222 void dns_udp_cancel_all_queries();
223
224 void dns_udp_send_simple_message(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass, u16 flags, async_done_callback *cb, void* cbargs);
225 void dns_udp_send_recursive_message(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass, u16 flags, async_done_callback *cb, void* cbargs);
226 ya_result dns_udp_send_simple_message_sync(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass,u16 flags, dns_simple_message_s **to_release);
227 ya_result dns_udp_send_recursive_message_sync(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass,u16 flags, dns_simple_message_s **to_release);
228
229 bool dns_udp_simple_message_trylock(dns_simple_message_s *simple_message);
230 void dns_udp_simple_message_lock(dns_simple_message_s *simple_message);
231 void dns_udp_simple_message_unlock(dns_simple_message_s *simple_message);
232
233 void dns_udp_simple_message_retain(dns_simple_message_s *simple_message);
234 void dns_udp_simple_message_release(dns_simple_message_s *simple_message);
235
dns_udp_simple_message_get_answer(const dns_simple_message_s * simple_message)236 static inline const message_data *dns_udp_simple_message_get_answer(const dns_simple_message_s *simple_message)
237 {
238 return simple_message->answer;
239 }
240
241 u32 dns_udp_send_queue_size();
242 u32 dns_udp_pending_queries_count();
243 u32 dns_udp_pending_feedback_count();
244
245 /**
246 */
247
248 typedef bool dns_udp_query_hook(dns_simple_message_s *simple_message, message_data *mesg);
249
250 /**
251 * Sets a hook for queries.
252 *
253 * The hook is called by the service on each messages and is expected to answer
254 * TRUE if it wrote an answer on it
255 * FALSE if it did not
256 *
257 * Every use of the dns_udp service is affected by this.
258 * Only one hook is possible at a given time.
259 *
260 * @param hook a function or NULL to reset to no HOOK.
261 */
262
263 void dns_udp_set_query_hook(dns_udp_query_hook *hook);
264
265 /**
266 *
267 * Mark a simple message as being timed-out
268 * Meant for use in hooks.
269 * Use with care.
270 *
271 * @param simple_message
272 */
273
274 void dns_udp_mark_as_timedout(dns_simple_message_s *simple_message);
275
276 #endif // DNS_UDP_H
277
278