1 /* ==========================================================================
2  * dns.h - Recursive, Reentrant DNS Resolver.
3  * --------------------------------------------------------------------------
4  * Copyright (c) 2009, 2010, 2012-2015  William Ahern
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to permit
11  * persons to whom the Software is furnished to do so, subject to the
12  * following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20  * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23  * USE OR OTHER DEALINGS IN THE SOFTWARE.
24  * ==========================================================================
25  */
26 #ifndef DNS_H
27 #define DNS_H
28 
29 #include <stddef.h>		/* size_t offsetof() */
30 #include <stdint.h>		/* uint64_t */
31 #include <stdio.h>		/* FILE */
32 #include <string.h>		/* strlen(3) */
33 #include <time.h>		/* struct timespec time_t */
34 
35 #if _WIN32
36 #include <winsock2.h>
37 #include <ws2tcpip.h>
38 #else
39 #include <sys/param.h>		/* BYTE_ORDER BIG_ENDIAN _BIG_ENDIAN */
40 #include <sys/types.h>		/* socklen_t */
41 #include <sys/socket.h>		/* struct socket */
42 #include <poll.h>		/* POLLIN POLLOUT */
43 #include <netinet/in.h>		/* struct in_addr struct in6_addr */
44 #include <netdb.h>		/* struct addrinfo */
45 #endif
46 
47 
48 /*
49  * V I S I B I L I T Y
50  *
51  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
52 
53 #ifndef DNS_PUBLIC
54 #define DNS_PUBLIC
55 #endif
56 
57 
58 /*
59  * V E R S I O N
60  *
61  * Vendor: Entity for which versions numbers are relevant. (If forking
62  * change DNS_VENDOR to avoid confusion.)
63  *
64  * Three versions:
65  *
66  * REL	Official "release"--bug fixes, new features, etc.
67  * ABI	Changes to existing object sizes or parameter types
68  * API	Changes that might effect application source.
69  *
70  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
71 
72 #define DNS_VENDOR "william@25thandClement.com"
73 
74 #define DNS_V_REL  0x20160809
75 #define DNS_V_ABI  0x20160608
76 #define DNS_V_API  0x20160809
77 
78 
79 DNS_PUBLIC const char *dns_vendor(void);
80 
81 DNS_PUBLIC int dns_v_rel(void);
82 DNS_PUBLIC int dns_v_abi(void);
83 DNS_PUBLIC int dns_v_api(void);
84 
85 
86 /*
87  * E R R O R S
88  *
89  * Errors and exceptions are always returned through an int. This should
90  * hopefully make integration easier in the majority of circumstances, and
91  * also cut down on useless compiler warnings.
92  *
93  * System and library errors are returned together. POSIX guarantees that
94  * all system errors are positive integers. Library errors are always
95  * negative integers in the range DNS_EBASE to DNS_ELAST, with the high bits
96  * set to the three magic ASCII characters "dns".
97  *
98  * dns_strerror() returns static English string descriptions of all known
99  * errors, and punts the remainder to strerror(3).
100  *
101  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
102 
103 #define DNS_EBASE -(('d' << 24) | ('n' << 16) | ('s' << 8) | 64)
104 
105 #define dns_error_t int /* for documentation only */
106 
107 enum dns_errno {
108 	DNS_ENOBUFS = DNS_EBASE,
109 	DNS_EILLEGAL,
110 	DNS_EORDER,
111 	DNS_ESECTION,
112 	DNS_EUNKNOWN,
113 	DNS_EADDRESS,
114 	DNS_ENOQUERY,
115 	DNS_ENOANSWER,
116 	DNS_EFETCHED,
117 	DNS_ESERVICE, /* EAI_SERVICE */
118 	DNS_ENONAME,  /* EAI_NONAME */
119 	DNS_EFAIL,    /* EAI_FAIL */
120 	DNS_ECONNFIN,
121 	DNS_EVERIFY,
122 	DNS_ELAST,
123 }; /* dns_errno */
124 
125 DNS_PUBLIC const char *dns_strerror(dns_error_t);
126 
127 DNS_PUBLIC int *dns_debug_p(void);
128 
129 #define dns_debug (*dns_debug_p()) /* was extern int dns_debug before 20160523 API */
130 
131 
132 /*
133  * C O M P I L E R  A N N O T A T I O N S
134  *
135  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
136 
137 #if defined __clang__
138 #define DNS_PRAGMA_PUSH _Pragma("clang diagnostic push")
139 #define DNS_PRAGMA_QUIET _Pragma("clang diagnostic ignored \"-Winitializer-overrides\"")
140 #define DNS_PRAGMA_POP _Pragma("clang diagnostic pop")
141 
142 #elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4
143 #define DNS_PRAGMA_PUSH _Pragma("GCC diagnostic push")
144 #define DNS_PRAGMA_QUIET _Pragma("GCC diagnostic ignored \"-Woverride-init\"")
145 #define DNS_PRAGMA_POP _Pragma("GCC diagnostic pop")
146 
147 #else
148 #define DNS_PRAGMA_PUSH
149 #define DNS_PRAGMA_QUIET
150 #define DNS_PRAGMA_POP
151 #endif
152 
153 #if defined __GNUC__
154 #define DNS_PRAGMA_EXTENSION __extension__
155 #else
156 #define DNS_PRAGMA_EXTENSION
157 #endif
158 
159 
160 /*
161  * E V E N T S  I N T E R F A C E S
162  *
163  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
164 
165 #if defined(POLLIN)
166 #define DNS_POLLIN POLLIN
167 #else
168 #define DNS_POLLIN  1
169 #endif
170 
171 #if defined(POLLOUT)
172 #define DNS_POLLOUT POLLOUT
173 #else
174 #define DNS_POLLOUT 2
175 #endif
176 
177 
178 /*
179  * See Application Interface below for configuring libevent bitmasks instead
180  * of poll(2) bitmasks.
181  */
182 #define DNS_EVREAD  2
183 #define DNS_EVWRITE 4
184 
185 
186 #define DNS_POLL2EV(set) \
187 	(((set) & DNS_POLLIN)? DNS_EVREAD : 0) | (((set) & DNS_POLLOUT)? DNS_EVWRITE : 0)
188 
189 #define DNS_EV2POLL(set) \
190 	(((set) & DNS_EVREAD)? DNS_POLLIN : 0) | (((set) & DNS_EVWRITE)? DNS_POLLOUT : 0)
191 
192 
193 /*
194  * E N U M E R A T I O N  I N T E R F A C E S
195  *
196  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
197 
198 enum dns_section {
199 	DNS_S_QD		= 0x01,
200 #define DNS_S_QUESTION		DNS_S_QD
201 
202 	DNS_S_AN		= 0x02,
203 #define DNS_S_ANSWER		DNS_S_AN
204 
205 	DNS_S_NS		= 0x04,
206 #define DNS_S_AUTHORITY		DNS_S_NS
207 
208 	DNS_S_AR		= 0x08,
209 #define DNS_S_ADDITIONAL	DNS_S_AR
210 
211 	DNS_S_ALL		= 0x0f
212 }; /* enum dns_section */
213 
214 
215 enum dns_class {
216 	DNS_C_IN	= 1,
217 
218 	DNS_C_ANY	= 255
219 }; /* enum dns_class */
220 
221 
222 enum dns_type {
223 	DNS_T_A		= 1,
224 	DNS_T_NS	= 2,
225 	DNS_T_CNAME	= 5,
226 	DNS_T_SOA	= 6,
227 	DNS_T_PTR	= 12,
228 	DNS_T_MX	= 15,
229 	DNS_T_TXT	= 16,
230 	DNS_T_AAAA	= 28,
231 	DNS_T_SRV	= 33,
232 	DNS_T_OPT	= 41,
233 	DNS_T_SSHFP	= 44,
234 	DNS_T_SPF	= 99,
235 	DNS_T_AXFR      = 252,
236 
237 	DNS_T_ALL	= 255
238 }; /* enum dns_type */
239 
240 
241 enum dns_opcode {
242 	DNS_OP_QUERY	= 0,
243 	DNS_OP_IQUERY	= 1,
244 	DNS_OP_STATUS	= 2,
245 	DNS_OP_NOTIFY	= 4,
246 	DNS_OP_UPDATE	= 5,
247 }; /* dns_opcode */
248 
249 
250 enum dns_rcode {
251 	DNS_RC_NOERROR	= 0,
252 	DNS_RC_FORMERR	= 1,
253 	DNS_RC_SERVFAIL	= 2,
254 	DNS_RC_NXDOMAIN	= 3,
255 	DNS_RC_NOTIMP	= 4,
256 	DNS_RC_REFUSED	= 5,
257 	DNS_RC_YXDOMAIN	= 6,
258 	DNS_RC_YXRRSET	= 7,
259 	DNS_RC_NXRRSET	= 8,
260 	DNS_RC_NOTAUTH	= 9,
261 	DNS_RC_NOTZONE	= 10,
262 
263 	/* EDNS(0) extended RCODEs */
264 	DNS_RC_BADVERS = 16,
265 }; /* dns_rcode */
266 
267 
268 /*
269  * NOTE: These string functions need a small buffer in case the literal
270  * integer value needs to be printed and returned. UNLESS this buffer is
271  * SPECIFIED, the returned string has ONLY BLOCK SCOPE.
272  */
273 #define DNS_STRMAXLEN 47 /* "QUESTION|ANSWER|AUTHORITY|ADDITIONAL" */
274 
275 DNS_PUBLIC const char *dns_strsection(enum dns_section, char *);
276 
277 DNS_PUBLIC enum dns_section dns_isection(const char *);
278 
279 DNS_PUBLIC const char *dns_strclass(enum dns_class, char *);
280 
281 DNS_PUBLIC enum dns_class dns_iclass(const char *);
282 
283 DNS_PUBLIC const char *dns_strtype(enum dns_type, char *);
284 
285 DNS_PUBLIC enum dns_type dns_itype(const char *);
286 
287 DNS_PUBLIC const char *dns_stropcode(enum dns_opcode);
288 
289 DNS_PUBLIC enum dns_opcode dns_iopcode(const char *);
290 
291 DNS_PUBLIC const char *dns_strrcode(enum dns_rcode);
292 
293 DNS_PUBLIC enum dns_rcode dns_ircode(const char *);
294 
295 
296 /*
297  * A T O M I C  I N T E R F A C E S
298  *
299  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
300 
301 typedef unsigned long dns_atomic_t;
302 
303 typedef unsigned long dns_refcount_t; /* must be same value type as dns_atomic_t */
304 
305 
306 /*
307  * C R Y P T O  I N T E R F A C E S
308  *
309  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
310 
311 typedef unsigned dns_random_f(void);
312 
313 DNS_PUBLIC dns_random_f **dns_random_p(void);
314 
315 #define dns_random (*dns_random_p()) /* was extern unsigned (*dns_random)(void) before 20160523 API */
316 
317 
318 /*
319  * P A C K E T  I N T E R F A C E
320  *
321  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
322 
323 struct dns_header {
324 		unsigned qid:16;
325 
326 #if (defined BYTE_ORDER && BYTE_ORDER == BIG_ENDIAN) || (defined __sun && defined _BIG_ENDIAN)
327 		unsigned qr:1;
328 		unsigned opcode:4;
329 		unsigned aa:1;
330 		unsigned tc:1;
331 		unsigned rd:1;
332 
333 		unsigned ra:1;
334 		unsigned unused:3;
335 		unsigned rcode:4;
336 #else
337 		unsigned rd:1;
338 		unsigned tc:1;
339 		unsigned aa:1;
340 		unsigned opcode:4;
341 		unsigned qr:1;
342 
343 		unsigned rcode:4;
344 		unsigned unused:3;
345 		unsigned ra:1;
346 #endif
347 
348 		unsigned qdcount:16;
349 		unsigned ancount:16;
350 		unsigned nscount:16;
351 		unsigned arcount:16;
352 }; /* struct dns_header */
353 
354 #define dns_header(p)	(&(p)->header)
355 
356 
357 #ifndef DNS_P_QBUFSIZ
358 #define DNS_P_QBUFSIZ	dns_p_calcsize(256 + 4)
359 #endif
360 
361 #ifndef DNS_P_DICTSIZE
362 #define DNS_P_DICTSIZE	16
363 #endif
364 
365 struct dns_packet {
366 	unsigned short dict[DNS_P_DICTSIZE];
367 
368 	struct dns_p_memo {
369 		struct dns_s_memo {
370 			unsigned short base, end;
371 		} qd, an, ns, ar;
372 
373 		struct {
374 			unsigned short p;
375 			unsigned short maxudp;
376 			unsigned ttl;
377 		} opt;
378 	} memo;
379 
380 	struct { struct dns_packet *cqe_next, *cqe_prev; } cqe;
381 
382 	size_t size, end;
383 
384 	int:16; /* tcp padding */
385 
386 	DNS_PRAGMA_EXTENSION union {
387 		struct dns_header header;
388 		unsigned char data[1];
389 	};
390 }; /* struct dns_packet */
391 
392 #define dns_p_calcsize(n)	(offsetof(struct dns_packet, data) + DNS_PP_MAX(12, (n)))
393 
394 #define dns_p_sizeof(P)		dns_p_calcsize((P)->end)
395 
396 /** takes size of entire packet structure as allocated */
397 DNS_PUBLIC struct dns_packet *dns_p_init(struct dns_packet *, size_t);
398 
399 /** takes size of maximum desired payload */
400 DNS_PUBLIC struct dns_packet *dns_p_make(size_t, int *);
401 
402 DNS_PUBLIC int dns_p_grow(struct dns_packet **);
403 
404 DNS_PUBLIC struct dns_packet *dns_p_copy(struct dns_packet *, const struct dns_packet *);
405 
406 #define dns_p_opcode(P)		(dns_header(P)->opcode)
407 
408 DNS_PUBLIC enum dns_rcode dns_p_rcode(struct dns_packet *);
409 
410 DNS_PUBLIC unsigned dns_p_count(struct dns_packet *, enum dns_section);
411 
412 DNS_PUBLIC int dns_p_push(struct dns_packet *, enum dns_section, const void *, size_t, enum dns_type, enum dns_class, unsigned, const void *);
413 
414 DNS_PUBLIC void dns_p_dictadd(struct dns_packet *, unsigned short);
415 
416 DNS_PUBLIC struct dns_packet *dns_p_merge(struct dns_packet *, enum dns_section, struct dns_packet *, enum dns_section, int *);
417 
418 DNS_PUBLIC void dns_p_dump(struct dns_packet *, FILE *);
419 
420 DNS_PUBLIC int dns_p_study(struct dns_packet *);
421 
422 
423 /*
424  * D O M A I N  N A M E  I N T E R F A C E S
425  *
426  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
427 
428 #define DNS_D_MAXLABEL	63	/* + 1 '\0' */
429 #define DNS_D_MAXNAME	255	/* + 1 '\0' */
430 
431 #define DNS_D_ANCHOR	1	/* anchor domain w/ root "." */
432 #define DNS_D_CLEAVE	2	/* cleave sub-domain */
433 #define DNS_D_TRIM	4	/* remove superfluous dots */
434 
435 DNS_PUBLIC char *dns_d_init(void *, size_t, const void *, size_t, int);
436 
437 DNS_PUBLIC size_t dns_d_anchor(void *, size_t, const void *, size_t);
438 
439 DNS_PUBLIC size_t dns_d_cleave(void *, size_t, const void *, size_t);
440 
441 DNS_PUBLIC size_t dns_d_comp(void *, size_t, const void *, size_t, struct dns_packet *, int *);
442 
443 DNS_PUBLIC size_t dns_d_expand(void *, size_t, unsigned short, struct dns_packet *, int *);
444 
445 DNS_PUBLIC unsigned short dns_d_skip(unsigned short, struct dns_packet *);
446 
447 DNS_PUBLIC int dns_d_push(struct dns_packet *, const void *, size_t);
448 
449 DNS_PUBLIC size_t dns_d_cname(void *, size_t, const void *, size_t, struct dns_packet *, int *error);
450 
451 
452 /*
453  * R E S O U R C E  R E C O R D  I N T E R F A C E S
454  *
455  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
456 
457 struct dns_rr {
458 	enum dns_section section;
459 
460 	struct {
461 		unsigned short p;
462 		unsigned short len;
463 	} dn;
464 
465 	enum dns_type type;
466 	enum dns_class class;
467 	unsigned ttl;
468 
469 	struct {
470 		unsigned short p;
471 		unsigned short len;
472 	} rd;
473 }; /* struct dns_rr */
474 
475 
476 DNS_PUBLIC int dns_rr_copy(struct dns_packet *, struct dns_rr *, struct dns_packet *);
477 
478 DNS_PUBLIC int dns_rr_parse(struct dns_rr *, unsigned short, struct dns_packet *);
479 
480 DNS_PUBLIC unsigned short dns_rr_skip(unsigned short, struct dns_packet *);
481 
482 DNS_PUBLIC int dns_rr_cmp(struct dns_rr *, struct dns_packet *, struct dns_rr *, struct dns_packet *);
483 
484 DNS_PUBLIC size_t dns_rr_print(void *, size_t, struct dns_rr *, struct dns_packet *, int *);
485 
486 
487 struct dns_rr_i {
488 	enum dns_section section;
489 	const void *name;
490 	enum dns_type type;
491 	enum dns_class class;
492 	const void *data;
493 
494 	int follow;
495 
496 	int (*sort)(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
497 	unsigned args[2];
498 
499 	struct {
500 		unsigned short next;
501 		unsigned short count;
502 
503 		unsigned exec;
504 		unsigned regs[2];
505 	} state, saved;
506 }; /* struct dns_rr_i */
507 
508 DNS_PUBLIC int dns_rr_i_packet(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
509 
510 DNS_PUBLIC int dns_rr_i_order(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
511 
512 DNS_PUBLIC int dns_rr_i_shuffle(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
513 
514 DNS_PUBLIC void dns_rr_i_init(struct dns_rr_i *);
515 
516 #define dns_rr_i_save(i)	((i)->saved = (i)->state)
517 #define dns_rr_i_rewind(i)	((i)->state = (i)->saved)
518 #define dns_rr_i_count(i)	((i)->state.count)
519 
520 DNS_PUBLIC unsigned dns_rr_grep(struct dns_rr *, unsigned, struct dns_rr_i *, struct dns_packet *, int *);
521 
522 #define dns_rr_foreach_(rr, P, ...)	\
523 	for (struct dns_rr_i DNS_PP_XPASTE(i, __LINE__) = { __VA_ARGS__ }; dns_rr_grep((rr), 1, &DNS_PP_XPASTE(i, __LINE__), (P), NULL); )
524 
525 #define dns_rr_foreach(...)	dns_rr_foreach_(__VA_ARGS__)
526 
527 
528 /*
529  * A  R E S O U R C E  R E C O R D
530  */
531 
532 struct dns_a {
533 	struct in_addr addr;
534 }; /* struct dns_a */
535 
536 DNS_PUBLIC int dns_a_parse(struct dns_a *, struct dns_rr *, struct dns_packet *);
537 
538 DNS_PUBLIC int dns_a_push(struct dns_packet *, struct dns_a *);
539 
540 DNS_PUBLIC int dns_a_cmp(const struct dns_a *, const struct dns_a *);
541 
542 DNS_PUBLIC size_t dns_a_print(void *, size_t, struct dns_a *);
543 
544 DNS_PUBLIC size_t dns_a_arpa(void *, size_t, const struct dns_a *);
545 
546 
547 /*
548  * AAAA  R E S O U R C E  R E C O R D
549  */
550 
551 struct dns_aaaa {
552 	struct in6_addr addr;
553 }; /* struct dns_aaaa */
554 
555 DNS_PUBLIC int dns_aaaa_parse(struct dns_aaaa *, struct dns_rr *, struct dns_packet *);
556 
557 DNS_PUBLIC int dns_aaaa_push(struct dns_packet *, struct dns_aaaa *);
558 
559 DNS_PUBLIC int dns_aaaa_cmp(const struct dns_aaaa *, const struct dns_aaaa *);
560 
561 DNS_PUBLIC size_t dns_aaaa_print(void *, size_t, struct dns_aaaa *);
562 
563 DNS_PUBLIC size_t dns_aaaa_arpa(void *, size_t, const struct dns_aaaa *);
564 
565 
566 /*
567  * MX  R E S O U R C E  R E C O R D
568  */
569 
570 struct dns_mx {
571 	unsigned short preference;
572 	char host[DNS_D_MAXNAME + 1];
573 }; /* struct dns_mx */
574 
575 DNS_PUBLIC int dns_mx_parse(struct dns_mx *, struct dns_rr *, struct dns_packet *);
576 
577 DNS_PUBLIC int dns_mx_push(struct dns_packet *, struct dns_mx *);
578 
579 DNS_PUBLIC int dns_mx_cmp(const struct dns_mx *, const struct dns_mx *);
580 
581 DNS_PUBLIC size_t dns_mx_print(void *, size_t, struct dns_mx *);
582 
583 DNS_PUBLIC size_t dns_mx_cname(void *, size_t, struct dns_mx *);
584 
585 
586 /*
587  * NS  R E S O U R C E  R E C O R D
588  */
589 
590 struct dns_ns {
591 	char host[DNS_D_MAXNAME + 1];
592 }; /* struct dns_ns */
593 
594 DNS_PUBLIC int dns_ns_parse(struct dns_ns *, struct dns_rr *, struct dns_packet *);
595 
596 DNS_PUBLIC int dns_ns_push(struct dns_packet *, struct dns_ns *);
597 
598 DNS_PUBLIC int dns_ns_cmp(const struct dns_ns *, const struct dns_ns *);
599 
600 DNS_PUBLIC size_t dns_ns_print(void *, size_t, struct dns_ns *);
601 
602 DNS_PUBLIC size_t dns_ns_cname(void *, size_t, struct dns_ns *);
603 
604 
605 /*
606  * CNAME  R E S O U R C E  R E C O R D
607  */
608 
609 struct dns_cname {
610 	char host[DNS_D_MAXNAME + 1];
611 }; /* struct dns_cname */
612 
613 DNS_PUBLIC int dns_cname_parse(struct dns_cname *, struct dns_rr *, struct dns_packet *);
614 
615 DNS_PUBLIC int dns_cname_push(struct dns_packet *, struct dns_cname *);
616 
617 DNS_PUBLIC int dns_cname_cmp(const struct dns_cname *, const struct dns_cname *);
618 
619 DNS_PUBLIC size_t dns_cname_print(void *, size_t, struct dns_cname *);
620 
621 DNS_PUBLIC size_t dns_cname_cname(void *, size_t, struct dns_cname *);
622 
623 
624 /*
625  * SOA  R E S O U R C E  R E C O R D
626  */
627 
628 struct dns_soa {
629 	char mname[DNS_D_MAXNAME + 1];
630 	char rname[DNS_D_MAXNAME + 1];
631 	unsigned serial, refresh, retry, expire, minimum;
632 }; /* struct dns_soa */
633 
634 DNS_PUBLIC int dns_soa_parse(struct dns_soa *, struct dns_rr *, struct dns_packet *);
635 
636 DNS_PUBLIC int dns_soa_push(struct dns_packet *, struct dns_soa *);
637 
638 DNS_PUBLIC int dns_soa_cmp(const struct dns_soa *, const struct dns_soa *);
639 
640 DNS_PUBLIC size_t dns_soa_print(void *, size_t, struct dns_soa *);
641 
642 
643 /*
644  * PTR  R E S O U R C E  R E C O R D
645  */
646 
647 struct dns_ptr {
648 	char host[DNS_D_MAXNAME + 1];
649 }; /* struct dns_ptr */
650 
651 DNS_PUBLIC int dns_ptr_parse(struct dns_ptr *, struct dns_rr *, struct dns_packet *);
652 
653 DNS_PUBLIC int dns_ptr_push(struct dns_packet *, struct dns_ptr *);
654 
655 DNS_PUBLIC int dns_ptr_cmp(const struct dns_ptr *, const struct dns_ptr *);
656 
657 DNS_PUBLIC size_t dns_ptr_print(void *, size_t, struct dns_ptr *);
658 
659 DNS_PUBLIC size_t dns_ptr_cname(void *, size_t, struct dns_ptr *);
660 
661 DNS_PUBLIC size_t dns_ptr_qname(void *, size_t, int, void *);
662 
663 
664 /*
665  * SRV  R E S O U R C E  R E C O R D
666  */
667 
668 struct dns_srv {
669 	unsigned short priority;
670 	unsigned short weight;
671 	unsigned short port;
672 	char target[DNS_D_MAXNAME + 1];
673 }; /* struct dns_srv */
674 
675 DNS_PUBLIC int dns_srv_parse(struct dns_srv *, struct dns_rr *, struct dns_packet *);
676 
677 DNS_PUBLIC int dns_srv_push(struct dns_packet *, struct dns_srv *);
678 
679 DNS_PUBLIC int dns_srv_cmp(const struct dns_srv *, const struct dns_srv *);
680 
681 DNS_PUBLIC size_t dns_srv_print(void *, size_t, struct dns_srv *);
682 
683 DNS_PUBLIC size_t dns_srv_cname(void *, size_t, struct dns_srv *);
684 
685 
686 /*
687  * OPT  R E S O U R C E  R E C O R D
688  */
689 
690 #ifndef DNS_OPT_MINDATA
691 #define DNS_OPT_MINDATA 256
692 #endif
693 
694 #define DNS_OPT_DNSSEC  0x8000
695 
696 struct dns_opt {
697 	enum dns_rcode rcode;
698 	unsigned char version;
699 	unsigned short flags;
700 
701 	union {
702 		unsigned short maxsize; /* deprecated as confusing */
703 		unsigned short maxudp; /* maximum UDP payload size */
704 	};
705 
706 	size_t size, len;
707 	unsigned char data[DNS_OPT_MINDATA];
708 }; /* struct dns_opt */
709 
710 #define DNS_OPT_INIT(opt) { .size = sizeof (*opt) - offsetof(struct dns_opt, data) }
711 
712 DNS_PUBLIC struct dns_opt *dns_opt_init(struct dns_opt *, size_t);
713 
714 DNS_PUBLIC int dns_opt_parse(struct dns_opt *, struct dns_rr *, struct dns_packet *);
715 
716 DNS_PUBLIC int dns_opt_push(struct dns_packet *, struct dns_opt *);
717 
718 DNS_PUBLIC int dns_opt_cmp(const struct dns_opt *, const struct dns_opt *);
719 
720 DNS_PUBLIC size_t dns_opt_print(void *, size_t, struct dns_opt *);
721 
722 DNS_PUBLIC unsigned int dns_opt_ttl(const struct dns_opt *);
723 
724 DNS_PUBLIC unsigned short dns_opt_class(const struct dns_opt *);
725 
726 DNS_PUBLIC dns_error_t dns_opt_data_push(struct dns_opt *, unsigned char, unsigned short, const void *);
727 
728 
729 /*
730  * SSHFP  R E S O U R C E  R E C O R D
731  */
732 
733 struct dns_sshfp {
734 	enum dns_sshfp_key {
735 		DNS_SSHFP_RSA = 1,
736 		DNS_SSHFP_DSA = 2,
737 	} algo;
738 
739 	enum dns_sshfp_digest {
740 		DNS_SSHFP_SHA1 = 1,
741 	} type;
742 
743 	union {
744 		unsigned char sha1[20];
745 	} digest;
746 }; /* struct dns_sshfp */
747 
748 DNS_PUBLIC int dns_sshfp_parse(struct dns_sshfp *, struct dns_rr *, struct dns_packet *);
749 
750 DNS_PUBLIC int dns_sshfp_push(struct dns_packet *, struct dns_sshfp *);
751 
752 DNS_PUBLIC int dns_sshfp_cmp(const struct dns_sshfp *, const struct dns_sshfp *);
753 
754 DNS_PUBLIC size_t dns_sshfp_print(void *, size_t, struct dns_sshfp *);
755 
756 
757 /*
758  * TXT  R E S O U R C E  R E C O R D
759  */
760 
761 #ifndef DNS_TXT_MINDATA
762 #define DNS_TXT_MINDATA	1024
763 #endif
764 
765 struct dns_txt {
766 	size_t size, len;
767 	unsigned char data[DNS_TXT_MINDATA];
768 }; /* struct dns_txt */
769 
770 DNS_PUBLIC struct dns_txt *dns_txt_init(struct dns_txt *, size_t);
771 
772 DNS_PUBLIC int dns_txt_parse(struct dns_txt *, struct dns_rr *, struct dns_packet *);
773 
774 DNS_PUBLIC int dns_txt_push(struct dns_packet *, struct dns_txt *);
775 
776 DNS_PUBLIC int dns_txt_cmp(const struct dns_txt *, const struct dns_txt *);
777 
778 DNS_PUBLIC size_t dns_txt_print(void *, size_t, struct dns_txt *);
779 
780 
781 /*
782  * ANY  R E S O U R C E  R E C O R D
783  */
784 
785 union dns_any {
786 	struct dns_a a;
787 	struct dns_aaaa aaaa;
788 	struct dns_mx mx;
789 	struct dns_ns ns;
790 	struct dns_cname cname;
791 	struct dns_soa soa;
792 	struct dns_ptr ptr;
793 	struct dns_srv srv;
794 	struct dns_opt opt;
795 	struct dns_sshfp sshfp;
796 	struct dns_txt txt, spf, rdata;
797 }; /* union dns_any */
798 
799 #define DNS_ANY_INIT(any) { .rdata = { .size = sizeof *(any) - offsetof(struct dns_txt, data) } }
800 
801 DNS_PUBLIC union dns_any *dns_any_init(union dns_any *, size_t);
802 
803 DNS_PUBLIC int dns_any_parse(union dns_any *, struct dns_rr *, struct dns_packet *);
804 
805 DNS_PUBLIC int dns_any_push(struct dns_packet *, union dns_any *, enum dns_type);
806 
807 DNS_PUBLIC int dns_any_cmp(const union dns_any *, enum dns_type, const union dns_any *, enum dns_type);
808 
809 DNS_PUBLIC size_t dns_any_print(void *, size_t, union dns_any *, enum dns_type);
810 
811 DNS_PUBLIC size_t dns_any_cname(void *, size_t, union dns_any *, enum dns_type);
812 
813 
814 /*
815  * H O S T S  I N T E R F A C E
816  *
817  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
818 
819 struct dns_hosts;
820 
821 DNS_PUBLIC struct dns_hosts *dns_hosts_open(int *);
822 
823 DNS_PUBLIC void dns_hosts_close(struct dns_hosts *);
824 
825 DNS_PUBLIC dns_refcount_t dns_hosts_acquire(struct dns_hosts *);
826 
827 DNS_PUBLIC dns_refcount_t dns_hosts_release(struct dns_hosts *);
828 
829 DNS_PUBLIC struct dns_hosts *dns_hosts_mortal(struct dns_hosts *);
830 
831 DNS_PUBLIC struct dns_hosts *dns_hosts_local(int *);
832 
833 DNS_PUBLIC int dns_hosts_loadfile(struct dns_hosts *, FILE *);
834 
835 DNS_PUBLIC int dns_hosts_loadpath(struct dns_hosts *, const char *);
836 
837 DNS_PUBLIC int dns_hosts_dump(struct dns_hosts *, FILE *);
838 
839 DNS_PUBLIC int dns_hosts_insert(struct dns_hosts *, int, const void *, const void *, _Bool);
840 
841 DNS_PUBLIC struct dns_packet *dns_hosts_query(struct dns_hosts *, struct dns_packet *, int *);
842 
843 
844 /*
845  * R E S O L V . C O N F  I N T E R F A C E
846  *
847  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
848 
849 struct dns_resolv_conf {
850 	struct sockaddr_storage nameserver[3];
851 
852 	char search[4][DNS_D_MAXNAME + 1];
853 
854 	/* (f)ile, (b)ind, (c)ache */
855 	char lookup[4 * (1 + (4 * 2))];
856 
857 	/* getaddrinfo family by preference order ("inet4", "inet6") */
858 	int family[3];
859 
860 	struct {
861 		_Bool edns0;
862 
863 		unsigned ndots;
864 
865 		unsigned timeout;
866 
867 		unsigned attempts;
868 
869 		_Bool rotate;
870 
871 		_Bool recurse;
872 
873 		_Bool smart;
874 
875 		enum {
876 			DNS_RESCONF_TCP_ENABLE,
877 			DNS_RESCONF_TCP_ONLY,
878 			DNS_RESCONF_TCP_SOCKS,
879 			DNS_RESCONF_TCP_DISABLE,
880 		} tcp;
881 	} options;
882 
883 	struct sockaddr_storage iface;
884 
885 	struct { /* PRIVATE */
886 		dns_atomic_t refcount;
887 	} _;
888 }; /* struct dns_resolv_conf */
889 
890 DNS_PUBLIC struct dns_resolv_conf *dns_resconf_open(int *);
891 
892 DNS_PUBLIC void dns_resconf_close(struct dns_resolv_conf *);
893 
894 DNS_PUBLIC dns_refcount_t dns_resconf_acquire(struct dns_resolv_conf *);
895 
896 DNS_PUBLIC dns_refcount_t dns_resconf_release(struct dns_resolv_conf *);
897 
898 DNS_PUBLIC struct dns_resolv_conf *dns_resconf_mortal(struct dns_resolv_conf *);
899 
900 DNS_PUBLIC struct dns_resolv_conf *dns_resconf_local(int *);
901 
902 DNS_PUBLIC struct dns_resolv_conf *dns_resconf_root(int *);
903 
904 DNS_PUBLIC int dns_resconf_pton(struct sockaddr_storage *, const char *);
905 
906 DNS_PUBLIC int dns_resconf_loadfile(struct dns_resolv_conf *, FILE *);
907 
908 DNS_PUBLIC int dns_resconf_loadpath(struct dns_resolv_conf *, const char *);
909 
910 DNS_PUBLIC int dns_nssconf_loadfile(struct dns_resolv_conf *, FILE *);
911 
912 DNS_PUBLIC int dns_nssconf_loadpath(struct dns_resolv_conf *, const char *);
913 
914 DNS_PUBLIC int dns_resconf_dump(struct dns_resolv_conf *, FILE *);
915 
916 DNS_PUBLIC int dns_nssconf_dump(struct dns_resolv_conf *, FILE *);
917 
918 DNS_PUBLIC int dns_resconf_setiface(struct dns_resolv_conf *, const char *, unsigned short);
919 
920 typedef unsigned long dns_resconf_i_t;
921 
922 DNS_PUBLIC size_t dns_resconf_search(void *, size_t, const void *, size_t, struct dns_resolv_conf *, dns_resconf_i_t *);
923 
924 
925 /*
926  * H I N T  S E R V E R  I N T E R F A C E
927  *
928  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
929 
930 struct dns_hints;
931 
932 DNS_PUBLIC struct dns_hints *dns_hints_open(struct dns_resolv_conf *, int *);
933 
934 DNS_PUBLIC void dns_hints_close(struct dns_hints *);
935 
936 DNS_PUBLIC dns_refcount_t dns_hints_acquire(struct dns_hints *);
937 
938 DNS_PUBLIC dns_refcount_t dns_hints_release(struct dns_hints *);
939 
940 DNS_PUBLIC struct dns_hints *dns_hints_mortal(struct dns_hints *);
941 
942 DNS_PUBLIC int dns_hints_insert(struct dns_hints *, const char *, const struct sockaddr *, unsigned);
943 
944 DNS_PUBLIC unsigned dns_hints_insert_resconf(struct dns_hints *, const char *, const struct dns_resolv_conf *, int *);
945 
946 DNS_PUBLIC struct dns_hints *dns_hints_local(struct dns_resolv_conf *, int *);
947 
948 DNS_PUBLIC struct dns_hints *dns_hints_root(struct dns_resolv_conf *, int *);
949 
950 DNS_PUBLIC struct dns_packet *dns_hints_query(struct dns_hints *, struct dns_packet *, int *);
951 
952 DNS_PUBLIC int dns_hints_dump(struct dns_hints *, FILE *);
953 
954 
955 struct dns_hints_i {
956 	const char *zone;
957 
958 	struct {
959 		unsigned next;
960 		unsigned seed;
961 	} state;
962 }; /* struct dns_hints_i */
963 
964 
965 DNS_PUBLIC unsigned dns_hints_grep(struct sockaddr **, socklen_t *, unsigned, struct dns_hints_i *, struct dns_hints *);
966 
967 
968 /*
969  * C A C H E  I N T E R F A C E
970  *
971  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
972 
973 struct dns_cache {
974 	void *state;
975 
976 	dns_refcount_t (*acquire)(struct dns_cache *);
977 	dns_refcount_t (*release)(struct dns_cache *);
978 
979 	struct dns_packet *(*query)(struct dns_packet *, struct dns_cache *, int *);
980 
981 	int (*submit)(struct dns_packet *, struct dns_cache *);
982 	int (*check)(struct dns_cache *);
983 	struct dns_packet *(*fetch)(struct dns_cache *, int *);
984 
985 	int (*pollfd)(struct dns_cache *);
986 	short (*events)(struct dns_cache *);
987 	void (*clear)(struct dns_cache *);
988 
989 	union {
990 		long i;
991 		void *p;
992 	} arg[3];
993 
994 	struct { /* PRIVATE */
995 		dns_atomic_t refcount;
996 	} _;
997 }; /* struct dns_cache */
998 
999 
1000 DNS_PUBLIC struct dns_cache *dns_cache_init(struct dns_cache *);
1001 
1002 DNS_PUBLIC void dns_cache_close(struct dns_cache *);
1003 
1004 
1005 /*
1006  * A P P L I C A T I O N  I N T E R F A C E
1007  *
1008  * Options to change the behavior of the API. Applies across all the
1009  * different components.
1010  *
1011  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1012 
1013 #define DNS_OPTS_INITIALIZER_ { 0, 0 }, 0, 0
1014 #define DNS_OPTS_INITIALIZER  { DNS_OPTS_INITIALIZER_ }
1015 
1016 struct dns_options {
1017 	/*
1018 	 * If the callback closes *fd, it must set it to -1. Otherwise, the
1019 	 * descriptor is queued and lazily closed at object destruction or
1020 	 * by an explicit call to _clear(). This allows safe use of
1021 	 * kqueue(2), epoll(2), et al -style persistent events.
1022 	 */
1023 	struct {
1024 		void *arg;
1025 		int (*cb)(int *fd, void *arg);
1026 	} closefd;
1027 
1028 	/* bitmask for _events() routines */
1029 	enum dns_events {
1030 		DNS_SYSPOLL,
1031 		DNS_LIBEVENT,
1032 	} events;
1033 
1034 	/* Use this SOCKS server.  */
1035 	const struct sockaddr_storage *socks_host;
1036 
1037 	/* Credentials for the SOCKS server (optional).  */
1038 	const char *socks_user;
1039 	const char *socks_password;
1040 }; /* struct dns_options */
1041 
1042 
1043 /*
1044  * S T A T S  I N T E R F A C E S
1045  *
1046  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1047 
1048 struct dns_stat {
1049 	size_t queries;
1050 
1051 	struct {
1052 		struct {
1053 			size_t count, bytes;
1054 		} sent, rcvd;
1055 	} udp, tcp;
1056 }; /* struct dns_stat */
1057 
1058 
1059 /*
1060  * S O C K E T  I N T E R F A C E
1061  *
1062  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1063 
1064 struct dns_socket;
1065 
1066 DNS_PUBLIC struct dns_socket *dns_so_open(const struct sockaddr *, int, const struct dns_options *, int *error);
1067 
1068 DNS_PUBLIC void dns_so_close(struct dns_socket *);
1069 
1070 DNS_PUBLIC void dns_so_reset(struct dns_socket *);
1071 
1072 DNS_PUBLIC unsigned short dns_so_mkqid(struct dns_socket *so);
1073 
1074 DNS_PUBLIC struct dns_packet *dns_so_query(struct dns_socket *, struct dns_packet *, struct sockaddr *, int *);
1075 
1076 DNS_PUBLIC int dns_so_submit(struct dns_socket *, struct dns_packet *, struct sockaddr *);
1077 
1078 DNS_PUBLIC int dns_so_check(struct dns_socket *);
1079 
1080 DNS_PUBLIC struct dns_packet *dns_so_fetch(struct dns_socket *, int *);
1081 
1082 DNS_PUBLIC time_t dns_so_elapsed(struct dns_socket *);
1083 
1084 DNS_PUBLIC void dns_so_clear(struct dns_socket *);
1085 
1086 DNS_PUBLIC int dns_so_events(struct dns_socket *);
1087 
1088 DNS_PUBLIC int dns_so_pollfd(struct dns_socket *);
1089 
1090 DNS_PUBLIC int dns_so_poll(struct dns_socket *, int);
1091 
1092 DNS_PUBLIC const struct dns_stat *dns_so_stat(struct dns_socket *);
1093 
1094 DNS_PUBLIC struct dns_trace *dns_so_trace(struct dns_socket *);
1095 
1096 DNS_PUBLIC void dns_so_settrace(struct dns_socket *, struct dns_trace *);
1097 
1098 
1099 /*
1100  * R E S O L V E R  I N T E R F A C E
1101  *
1102  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1103 
1104 struct dns_resolver;
1105 
1106 DNS_PUBLIC struct dns_resolver *dns_res_open(struct dns_resolv_conf *, struct dns_hosts *hosts, struct dns_hints *, struct dns_cache *, const struct dns_options *, int *);
1107 
1108 DNS_PUBLIC struct dns_resolver *dns_res_stub(const struct dns_options *, int *);
1109 
1110 DNS_PUBLIC void dns_res_reset(struct dns_resolver *);
1111 
1112 DNS_PUBLIC void dns_res_close(struct dns_resolver *);
1113 
1114 DNS_PUBLIC dns_refcount_t dns_res_acquire(struct dns_resolver *);
1115 
1116 DNS_PUBLIC dns_refcount_t dns_res_release(struct dns_resolver *);
1117 
1118 DNS_PUBLIC struct dns_resolver *dns_res_mortal(struct dns_resolver *);
1119 
1120 DNS_PUBLIC int dns_res_submit(struct dns_resolver *, const char *, enum dns_type, enum dns_class);
1121 
1122 DNS_PUBLIC int dns_res_submit2(struct dns_resolver *, const char *, size_t, enum dns_type, enum dns_class);
1123 
1124 DNS_PUBLIC int dns_res_check(struct dns_resolver *);
1125 
1126 DNS_PUBLIC struct dns_packet *dns_res_fetch(struct dns_resolver *, int *);
1127 
1128 DNS_PUBLIC time_t dns_res_elapsed(struct dns_resolver *);
1129 
1130 DNS_PUBLIC void dns_res_clear(struct dns_resolver *);
1131 
1132 DNS_PUBLIC int dns_res_events(struct dns_resolver *);
1133 
1134 DNS_PUBLIC int dns_res_pollfd(struct dns_resolver *);
1135 
1136 DNS_PUBLIC time_t dns_res_timeout(struct dns_resolver *);
1137 
1138 DNS_PUBLIC int dns_res_poll(struct dns_resolver *, int);
1139 
1140 DNS_PUBLIC struct dns_packet *dns_res_query(struct dns_resolver *, const char *, enum dns_type, enum dns_class, int, int *);
1141 
1142 DNS_PUBLIC const struct dns_stat *dns_res_stat(struct dns_resolver *);
1143 
1144 DNS_PUBLIC void dns_res_sethints(struct dns_resolver *, struct dns_hints *);
1145 
1146 DNS_PUBLIC struct dns_trace *dns_res_trace(struct dns_resolver *);
1147 
1148 DNS_PUBLIC void dns_res_settrace(struct dns_resolver *, struct dns_trace *);
1149 
1150 
1151 /*
1152  * A D D R I N F O  I N T E R F A C E
1153  *
1154  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1155 
1156 struct dns_addrinfo;
1157 
1158 DNS_PUBLIC struct dns_addrinfo *dns_ai_open(const char *, const char *, enum dns_type, const struct addrinfo *, struct dns_resolver *, int *);
1159 
1160 DNS_PUBLIC void dns_ai_close(struct dns_addrinfo *);
1161 
1162 DNS_PUBLIC int dns_ai_nextent(struct addrinfo **, struct dns_addrinfo *);
1163 
1164 DNS_PUBLIC size_t dns_ai_print(void *, size_t, struct addrinfo *, struct dns_addrinfo *);
1165 
1166 DNS_PUBLIC time_t dns_ai_elapsed(struct dns_addrinfo *);
1167 
1168 DNS_PUBLIC void dns_ai_clear(struct dns_addrinfo *);
1169 
1170 DNS_PUBLIC int dns_ai_events(struct dns_addrinfo *);
1171 
1172 DNS_PUBLIC int dns_ai_pollfd(struct dns_addrinfo *);
1173 
1174 DNS_PUBLIC time_t dns_ai_timeout(struct dns_addrinfo *);
1175 
1176 DNS_PUBLIC int dns_ai_poll(struct dns_addrinfo *, int);
1177 
1178 DNS_PUBLIC const struct dns_stat *dns_ai_stat(struct dns_addrinfo *);
1179 
1180 DNS_PUBLIC struct dns_trace *dns_ai_trace(struct dns_addrinfo *);
1181 
1182 DNS_PUBLIC void dns_ai_settrace(struct dns_addrinfo *, struct dns_trace *);
1183 
1184 
1185 /*
1186  * Q U E R Y  T R A C I N G  I N T E R F A C E
1187  *
1188  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1189 
1190 #define DNS_TRACE_ID_C(n) UINT64_C(n)
1191 typedef uint64_t dns_trace_id_t;
1192 
1193 #define DNS_TRACE_ABI 0x20160803
1194 
1195 struct dns_trace_event {
1196 	enum {
1197 		DNS_TE_RES_SUBMIT = 1,
1198 		DNS_TE_RES_FETCH = 99,
1199 
1200 		DNS_TE_SO_SUBMIT = 100,
1201 		DNS_TE_SO_VERIFY,
1202 		DNS_TE_SO_FETCH = 199,
1203 
1204 		DNS_TE_SYS_CONNECT = 200,
1205 		DNS_TE_SYS_SEND,
1206 		DNS_TE_SYS_RECV,
1207 	} type;
1208 
1209 	size_t size;
1210 	dns_trace_id_t id;
1211 	struct timespec ts;
1212 	int abi;
1213 
1214 	union {
1215 		struct {
1216 			char qname[DNS_D_MAXNAME + 1];
1217 			enum dns_type qtype;
1218 			enum dns_class qclass;
1219 			int error;
1220 		} res_submit;
1221 
1222 		struct {
1223 			int error;
1224 		} res_fetch;
1225 
1226 		struct {
1227 			struct sockaddr_storage haddr;
1228 			char hname[DNS_D_MAXNAME + 1];
1229 			int error;
1230 		} so_submit;
1231 
1232 		struct {
1233 			int error;
1234 		} so_verify;
1235 
1236 		struct {
1237 			int error;
1238 		} so_fetch;
1239 
1240 		struct {
1241 			struct sockaddr_storage src, dst;
1242 			int socktype;
1243 			dns_error_t error;
1244 		} sys_connect, sys_send, sys_recv;
1245 	};
1246 
1247 	unsigned char data[];
1248 };
1249 
dns_te_datasize(const struct dns_trace_event * te)1250 static inline size_t dns_te_datasize(const struct dns_trace_event *te) {
1251 	size_t n = offsetof(struct dns_trace_event, data);
1252 	return (n <= te->size)? te->size - n : 0;
1253 }
1254 
1255 struct dns_trace;
1256 
1257 DNS_PUBLIC int dns_trace_abi(void);
1258 
1259 DNS_PUBLIC struct dns_trace *dns_trace_open(FILE *, dns_error_t *);
1260 
1261 DNS_PUBLIC void dns_trace_close(struct dns_trace *);
1262 
1263 DNS_PUBLIC dns_refcount_t dns_trace_acquire(struct dns_trace *);
1264 
1265 DNS_PUBLIC dns_refcount_t dns_trace_release(struct dns_trace *);
1266 
1267 DNS_PUBLIC dns_trace_id_t dns_trace_id(struct dns_trace *);
1268 
1269 DNS_PUBLIC dns_trace_id_t dns_trace_setid(struct dns_trace *, dns_trace_id_t);
1270 
1271 DNS_PUBLIC struct dns_trace_event *dns_trace_get(struct dns_trace *, struct dns_trace_event **, dns_error_t *);
1272 
1273 DNS_PUBLIC struct dns_trace_event *dns_trace_tag(struct dns_trace *, struct dns_trace_event *);
1274 
1275 DNS_PUBLIC dns_error_t dns_trace_put(struct dns_trace *, const struct dns_trace_event *, const void *, size_t);
1276 
1277 DNS_PUBLIC dns_error_t dns_trace_dump(struct dns_trace *, FILE *);
1278 
1279 DNS_PUBLIC struct dns_trace_event *dns_trace_fget(struct dns_trace_event **, FILE *, dns_error_t *);
1280 
1281 DNS_PUBLIC dns_error_t dns_trace_fput(const struct dns_trace_event *, const void *, size_t, FILE *);
1282 
1283 
1284 /*
1285  * U T I L I T Y  I N T E R F A C E S
1286  *
1287  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1288 
1289 DNS_PUBLIC size_t dns_strlcpy(char *, const char *, size_t);
1290 
1291 DNS_PUBLIC size_t dns_strlcat(char *, const char *, size_t);
1292 
1293 
1294 /*
1295  * M A C R O  M A G I C S
1296  *
1297  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1298 
1299 #define DNS_PP_MIN(a, b) (((a) < (b))? (a) : (b))
1300 #define DNS_PP_MAX(a, b) (((a) > (b))? (a) : (b))
1301 #define DNS_PP_NARG_(a, b, c, d, e, f, g, h, i, j, k, N,...) N
1302 #define DNS_PP_NARG(...)	DNS_PP_NARG_(__VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
1303 #define DNS_PP_CALL(F, ...)	F(__VA_ARGS__)
1304 #define DNS_PP_PASTE(x, y)	x##y
1305 #define DNS_PP_XPASTE(x, y)	DNS_PP_PASTE(x, y)
1306 #define DNS_PP_STRINGIFY_(s)	#s
1307 #define DNS_PP_STRINGIFY(s)	DNS_PP_STRINGIFY_(s)
1308 #define DNS_PP_D1  0
1309 #define DNS_PP_D2  1
1310 #define DNS_PP_D3  2
1311 #define DNS_PP_D4  3
1312 #define DNS_PP_D5  4
1313 #define DNS_PP_D6  5
1314 #define DNS_PP_D7  6
1315 #define DNS_PP_D8  7
1316 #define DNS_PP_D9  8
1317 #define DNS_PP_D10 9
1318 #define DNS_PP_D11 10
1319 #define DNS_PP_DEC(N) DNS_PP_XPASTE(DNS_PP_D, N)
1320 
1321 #endif /* DNS_H */
1322