1 /**
2 *
3 * /brief type declarations private to the getdns library
4 *
5 * These type declarations are not meant to be used by applications calling
6 * the public library functions.
7 */
8
9 /*
10 * Copyright (c) 2013, NLnet Labs, Verisign, Inc.
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * * Neither the names of the copyright holders nor the
21 * names of its contributors may be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
28 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #ifndef TYPES_INTERNAL_H_
37 #define TYPES_INTERNAL_H_
38
39 #include "getdns/getdns.h"
40 #include "getdns/getdns_extra.h"
41 #include "util/rbtree.h"
42
43
44 /**
45 * this structure represents a single item in a list or dict
46 */
47 typedef union getdns_union {
48 void *ptr;
49 getdns_dict *dict;
50 getdns_list *list;
51 getdns_bindata *bindata;
52 uint32_t n;
53 } getdns_union;
54
55 typedef struct getdns_item {
56 getdns_data_type dtype;
57 getdns_union data;
58 } getdns_item;
59
60 typedef enum getdns_auth_state {
61 GETDNS_AUTH_NONE, /* Not tried (Oppotunistic)*/
62 GETDNS_AUTH_FAILED, /* Tried but failed or not possible*/
63 GETDNS_AUTH_OK, /* Tried and worked (Strict) */
64 } getdns_auth_state_t;
65
66 #define GETDNS_STR_AUTH_NONE "None"
67 #define GETDNS_STR_AUTH_FAILED "Failed"
68 #define GETDNS_STR_AUTH_OK "Success"
69
70 struct getdns_context;
71 struct getdns_upstreams;
72 struct getdns_upstream;
73
74 /* String constants for internal use */
75 #define GETDNS_STR_IPV4 "IPv4"
76 #define GETDNS_STR_IPV6 "IPv6"
77 #define GETDNS_STR_ADDRESS_TYPE "address_type"
78 #define GETDNS_STR_ADDRESS_DATA "address_data"
79 #define GETDNS_STR_PORT "port"
80 #define GETDNS_STR_EXTENSION_RETURN_BOTH_V4_AND_V6 "return_both_v4_and_v6"
81
82 #define GETDNS_STR_KEY_STATUS "status"
83 #define GETDNS_STR_KEY_REPLIES_TREE "replies_tree"
84 #define GETDNS_STR_KEY_REPLIES_FULL "replies_full"
85 #define GETDNS_STR_KEY_JUST_ADDRS "just_address_answers"
86 #define GETDNS_STR_KEY_CANONICAL_NM "canonical_name"
87 #define GETDNS_STR_KEY_ANSWER_TYPE "answer_type"
88 #define GETDNS_STR_KEY_INTERM_ALIASES "intermediate_aliases"
89 #define GETDNS_STR_KEY_NAME "name"
90 #define GETDNS_STR_KEY_HEADER "header"
91 #define GETDNS_STR_KEY_QUESTION "question"
92 #define GETDNS_STR_KEY_ANSWER "answer"
93 #define GETDNS_STR_KEY_TYPE "type"
94 #define GETDNS_STR_KEY_CLASS "class"
95 #define GETDNS_STR_KEY_TTL "ttl"
96 #define GETDNS_STR_KEY_RDATA "rdata"
97 #define GETDNS_STR_KEY_V4_ADDR "ipv4_address"
98 #define GETDNS_STR_KEY_V6_ADDR "ipv6_address"
99 #define GETDNS_STR_KEY_RDATA_RAW "rdata_raw"
100 #define GETDNS_STR_KEY_AUTHORITY "authority"
101 #define GETDNS_STR_KEY_ADDITIONAL "additional"
102 #define GETDNS_STR_KEY_QTYPE "qtype"
103 #define GETDNS_STR_KEY_QCLASS "qclass"
104 #define GETDNS_STR_KEY_QNAME "qname"
105 #define GETDNS_STR_KEY_QR "qr"
106 /* header flags */
107 #define GETDNS_STR_KEY_ID "id"
108 #define GETDNS_STR_KEY_OPCODE "opcode"
109 #define GETDNS_STR_KEY_RCODE "rcode"
110 #define GETDNS_STR_KEY_AA "aa"
111 #define GETDNS_STR_KEY_TC "tc"
112 #define GETDNS_STR_KEY_RD "rd"
113 #define GETDNS_STR_KEY_RA "ra"
114 #define GETDNS_STR_KEY_AD "ad"
115 #define GETDNS_STR_KEY_CD "cd"
116 #define GETDNS_STR_KEY_Z "z"
117 #define GETDNS_STR_KEY_QDCOUNT "qdcount"
118 #define GETDNS_STR_KEY_ANCOUNT "ancount"
119 #define GETDNS_STR_KEY_NSCOUNT "nscount"
120 #define GETDNS_STR_KEY_ARCOUNT "arcount"
121
122 #define TIMEOUT_FOREVER ((uint64_t)0xFFFFFFFFFFFFFFFF)
123 #define ASSERT_UNREACHABLE 0
124
125 #define GETDNS_TRANSPORTS_MAX 3
126 #define GETDNS_UPSTREAM_TRANSPORTS 2
127 #define GETDNS_TRANSPORT_FAIL_MULT 5
128
129
130 /* declarations */
131 struct getdns_dns_req;
132 struct getdns_network_req;
133
134 typedef void (*internal_cb_t)(struct getdns_dns_req *dns_req);
135
136 #define MF_PLAIN ((void *)&plain_mem_funcs_user_arg)
137 extern void *plain_mem_funcs_user_arg;
138
139 typedef union {
140 struct {
141 void *(*malloc)(size_t);
142 void *(*realloc)(void *, size_t);
143 void (*free)(void *);
144 } pln;
145 struct {
146 void *(*malloc)(void *userarg, size_t);
147 void *(*realloc)(void *userarg, void *, size_t);
148 void (*free)(void *userarg, void *);
149 } ext;
150 } mf_union;
151
152 struct mem_funcs {
153 void *mf_arg;
154 mf_union mf;
155 };
156
157 struct mem_funcs *
158 priv_getdns_context_mf(getdns_context *context);
159
160 typedef enum network_req_state_enum
161 {
162 NET_REQ_NOT_SENT = 0,
163 NET_REQ_IN_FLIGHT = 1,
164 NET_REQ_FINISHED = 2, /* Finish type in bits 2 and 3 */
165 NET_REQ_CANCELED = 6, /* 2 + (1 << 2) */
166 NET_REQ_TIMED_OUT = 10, /* 2 + (2 << 2) */
167 NET_REQ_ERRORED = 14 /* 2 + (3 << 2) */
168 } network_req_state;
169
170
171 /* State for async tcp stub resolving */
172 typedef struct getdns_tcp_state {
173
174 const uint8_t *write_buf;
175 size_t write_buf_len;
176 size_t written;
177
178 uint8_t *read_buf;
179 size_t read_buf_len;
180 uint8_t *read_pos;
181 size_t to_read;
182
183 } getdns_tcp_state;
184
185 /**
186 * Request data
187 **/
188 typedef struct getdns_network_req
189 {
190 /* For storage in upstream->netreq_by_query_id */
191 _getdns_rbnode_t node;
192 /* The netreq_by_query_id tree in which this netreq was registered */
193 _getdns_rbtree_t *query_id_registered;
194 #ifdef HAVE_MDNS_SUPPORT
195 /*
196 * for storage of continuous query context in hash table of cached results.
197 */
198 struct getdns_network_req * mdns_netreq_next;
199 #endif /* HAVE_MDNS_SUPPORT */
200 /* the async_id from unbound */
201 int unbound_id;
202 /* state var */
203 network_req_state state;
204 /* owner request (contains name) */
205 struct getdns_dns_req *owner;
206
207 /* request type */
208 uint16_t request_type;
209
210 /* dnssec status */
211 int dnssec_status;
212
213 /* tsig status:
214 * GETDNS_DNSSEC_INDETERMINATE means "No TSIG processing"
215 * GETDNS_DNSSEC_INSECURE means "TSIG sent, validate reply"
216 * GETDNS_DNSSEC_SECURE means "Validated"
217 * GETDNS_DNSSEC_BOGUS means "Validation failed"
218 */
219 int tsig_status;
220
221 getdns_redirects_t follow_redirects;
222
223 /* For stub resolving */
224 struct getdns_upstream *first_upstream;
225 struct getdns_upstream *upstream;
226 int fd;
227 getdns_transport_list_t transports[GETDNS_TRANSPORTS_MAX];
228 size_t transport_count;
229 size_t transport_current;
230 getdns_tls_authentication_t tls_auth_min;
231 getdns_eventloop_event event;
232
233 int edns_maximum_udp_payload_size;
234 uint16_t max_udp_payload_size;
235
236 size_t keepalive_sent;
237
238 /* Network requests scheduled to write after me */
239 struct getdns_network_req *write_queue_tail;
240
241 /* Some fields to record info for return_call_reporting */
242 uint64_t debug_start_time;
243 uint64_t debug_end_time;
244 getdns_auth_state_t debug_tls_auth_status;
245 getdns_bindata debug_tls_peer_cert;
246 const char *debug_tls_version;
247 size_t debug_udp;
248
249 /* When more space is needed for the wire_data response than is
250 * available in wire_data[], it will be allocated separately.
251 * response will then not point to wire_data anymore.
252 */
253 uint8_t *query;
254 uint8_t *opt; /* offset of OPT RR in query */
255
256 /* each network_req has a set of base options that are
257 * specific to the query, which are static and included when
258 * the network_req is created. When the query is sent out to
259 * a given upstream, some additional options are added that
260 * are specific to the upstream. There can be at most
261 * GETDNS_MAXIMUM_UPSTREAM_OPTION_SPACE bytes of
262 * upstream-specific options.
263
264 * use _getdns_network_req_clear_upstream_options() and
265 * _getdns_network_req_add_upstream_option() to fiddle with the
266 */
267 size_t base_query_option_sz;
268 size_t response_len;
269 uint8_t *response;
270 size_t wire_data_sz;
271 uint8_t wire_data[];
272
273 } getdns_network_req;
274
_getdns_netreq_finished(getdns_network_req * req)275 static inline int _getdns_netreq_finished(getdns_network_req *req)
276 { return !req || (req->state & NET_REQ_FINISHED); }
277
278 struct chain_head;
279 /**
280 * dns request - manages a number of network requests and
281 * the initial data passed to getdns_general
282 */
283 typedef struct getdns_dns_req {
284 /* For storage in context->outbound_requests */
285 _getdns_rbnode_t node;
286
287 /* name */
288 uint8_t name[256];
289 size_t name_len;
290
291 uint16_t request_class;
292
293 /* context that owns the request */
294 struct getdns_context *context;
295
296 getdns_append_name_t append_name;
297 const uint8_t *suffix;
298 size_t suffix_len;
299 unsigned suffix_appended : 1;
300
301 /* request extensions */
302 unsigned dnssec : 1;
303 unsigned dnssec_return_status : 1;
304 unsigned dnssec_return_only_secure : 1;
305 unsigned dnssec_return_all_statuses : 1;
306 unsigned dnssec_return_validation_chain : 1;
307 unsigned dnssec_return_full_validation_chain : 1;
308 unsigned dnssec_extension_set : 1;
309 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
310 unsigned dnssec_roadblock_avoidance : 1;
311 unsigned avoid_dnssec_roadblocks : 1;
312 #endif
313 unsigned edns_cookies : 1;
314 unsigned edns_client_subnet_private : 1;
315 unsigned return_call_reporting : 1;
316 unsigned add_warning_for_bad_dns : 1;
317
318 /* Internally used by return_validation_chain */
319 unsigned dnssec_ok_checking_disabled : 1;
320 unsigned is_sync_request : 1;
321 unsigned is_dns_request : 1;
322 unsigned request_timed_out : 1;
323
324 /* The validating and freed variables are used to make sure a single
325 * code path is followed while processing a DNS request, even when
326 * callbacks are already fired whilst the registering/scheduling call
327 * (i.e. ub_resolve_event) has not returned yet.
328 *
329 * validating is touched by _getdns_get_validation_chain only and
330 * freed is touched by _getdns_submit_netreq only
331 */
332 unsigned validating : 1;
333 unsigned waiting_for_ta : 1;
334 int *freed;
335
336 /* Validation chain to be canceled when this request is canceled */
337 struct chain_head *chain;
338
339 uint16_t tls_query_padding_blocksize;
340
341 /* internally scheduled request */
342 internal_cb_t internal_cb;
343
344 /* event loop */
345 getdns_eventloop *loop;
346
347 /* callback data */
348 getdns_callback_t user_callback;
349 void *user_pointer;
350
351 /* the transaction id */
352 getdns_transaction_t trans_id;
353
354 /* Absolute time (in milliseconds since epoch),
355 * after which this dns request is expired; i.e. timed out
356 */
357 uint64_t expires;
358
359 /* for scheduling timeouts when using libunbound */
360 getdns_eventloop_event timeout;
361
362 /* mem funcs */
363 struct mem_funcs my_mf;
364
365 /* Stuff for stub resolving */
366 struct getdns_upstreams *upstreams;
367
368 /* Linked list pointer for dns requests, for which answers are received
369 * from open connections as aside-effect of doing a synchronous call.
370 * See also the type definition of getdns_upstream in context.h for a
371 * more elaborate description.
372 */
373 struct getdns_dns_req *finished_next;
374
375 /* Linked list pointer for dns requests, which need to validate DNSSEC
376 * and are waiting for the root trust-anchors fetch.
377 */
378 struct getdns_dns_req *ta_notify;
379
380 /* network requests for this dns request.
381 * The array is terminated with NULL.
382 *
383 * Memory for these netreqs has been allocated by the same malloc
384 * operation that reserved space for this getdns_dns_req.
385 * They will thus be freed as part of the destruction of this struct,
386 * and do not need to be freed separately.
387 */
388 getdns_network_req *netreqs[];
389
390 } getdns_dns_req;
391
392 #define GETDNS_XMALLOC(obj, type, count) \
393 ((obj).mf_arg == MF_PLAIN \
394 ? ((type *)(*(obj).mf.pln.malloc)( (count)*sizeof(type))) \
395 : ((type *)(*(obj).mf.ext.malloc)((obj).mf_arg, (count)*sizeof(type))) \
396 )
397
398 #define GETDNS_XREALLOC(obj, ptr, type, count) \
399 ((obj).mf_arg == MF_PLAIN \
400 ? ((type *)(*(obj).mf.pln.realloc)( (ptr), (count)*sizeof(type))) \
401 : ((type *)(*(obj).mf.ext.realloc)( (obj).mf_arg \
402 , (ptr), (count)*sizeof(type))) \
403 )
404
405 #define GETDNS_FREE(obj, ptr) \
406 ((obj).mf_arg == MF_PLAIN \
407 ? ((*(obj).mf.pln.free)( (ptr))) \
408 : ((*(obj).mf.ext.free)((obj).mf_arg, (ptr))) \
409 )
410
411 #define GETDNS_NULL_FREE(obj, ptr) \
412 do { \
413 if (!(ptr)) \
414 break; \
415 if ((obj).mf_arg == MF_PLAIN) \
416 (*(obj).mf.pln.free)( (ptr)); \
417 else \
418 (*(obj).mf.ext.free)((obj).mf_arg, (ptr)); \
419 (ptr) = NULL; \
420 } while (0);
421
422 #define GETDNS_MALLOC(obj, type) GETDNS_XMALLOC(obj, type, 1)
423 #define GETDNS_REALLOC(obj, ptr, type) GETDNS_XREALLOC(obj, ptr, type, 1);
424
425
426 /* utility methods */
427
428 extern getdns_dict *dnssec_ok_checking_disabled;
429 extern getdns_dict *dnssec_ok_checking_disabled_roadblock_avoidance;
430 extern getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks;
431 extern getdns_dict *no_dnssec_checking_disabled_opportunistic;
432
433 /* dns request utils */
434 getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
435 const char *name, uint16_t request_type, const getdns_dict *extensions,
436 uint64_t *now_ms);
437
438 void _getdns_dns_req_free(getdns_dns_req * req);
439
440 /* network request utils */
441 getdns_return_t _getdns_network_req_add_upstream_option(getdns_network_req * req,
442 uint16_t code, uint16_t sz, const void* data);
443 void _getdns_network_req_clear_upstream_options(getdns_network_req * req);
444
445 /* Adds TSIG signature (if needed) and returns query length */
446 size_t _getdns_network_req_add_tsig(getdns_network_req *req);
447
448 void _getdns_network_validate_tsig(getdns_network_req *req);
449
450 void _getdns_netreq_reinit(getdns_network_req *netreq);
451
452 const char * _getdns_auth_str(getdns_auth_state_t auth);
453
454 #endif
455 /* types-internal.h */
456