1 /* ==========================================================================
2 * dns.h - Recursive, Reentrant DNS Resolver.
3 * --------------------------------------------------------------------------
4 * Copyright (c) 2009, 2010, 2012-2015 William Ahern
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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 * ==========================================================================
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 */
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 */
51 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
61 * Vendor: Entity for which versions numbers are relevant. (If forking
62 * change DNS_VENDOR to avoid confusion.)
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.
70 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
72 #define DNS_VENDOR "william@25thandClement.com"
74 #define DNS_V_REL 0x20160809
75 #define DNS_V_ABI 0x20160608
76 #define DNS_V_API 0x20160809
79 DNS_PUBLIC const char *dns_vendor(void);
81 DNS_PUBLIC int dns_v_rel(void);
82 DNS_PUBLIC int dns_v_abi(void);
83 DNS_PUBLIC int dns_v_api(void);
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.
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".
98 * dns_strerror() returns static English string descriptions of all known
99 * errors, and punts the remainder to strerror(3).
101 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
103 #define DNS_EBASE -(('d' << 24) | ('n' << 16) | ('s' << 8) | 64)
105 #define dns_error_t int /* for documentation only */
108 DNS_ENOBUFS = DNS_EBASE,
117 DNS_ESERVICE, /* EAI_SERVICE */
118 DNS_ENONAME, /* EAI_NONAME */
119 DNS_EFAIL, /* EAI_FAIL */
125 DNS_PUBLIC const char *dns_strerror(dns_error_t);
127 DNS_PUBLIC int *dns_debug_p(void);
129 #define dns_debug (*dns_debug_p()) /* was extern int dns_debug before 20160523 API */
133 * C O M P I L E R A N N O T A T I O N S
135 * GCC with -Wextra, and clang by default, complain about overrides in
136 * initializer lists. Overriding previous member initializers is well
137 * defined behavior in C. dns.c relies on this behavior to define default,
138 * overrideable member values when instantiating configuration objects.
140 * dns_quietinit() guards a compound literal expression with pragmas to
141 * silence these shrill warnings. This alleviates the burden of requiring
142 * third-party projects to adjust their compiler flags.
144 * NOTE: If you take the address of the compound literal, take the address
145 * of the transformed expression, otherwise the compound literal lifetime is
146 * tied to the scope of the GCC statement expression.
148 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
150 #if defined __clang__
151 #define DNS_PRAGMA_PUSH _Pragma("clang diagnostic push")
152 #define DNS_PRAGMA_QUIET _Pragma("clang diagnostic ignored \"-Winitializer-overrides\"")
153 #define DNS_PRAGMA_POP _Pragma("clang diagnostic pop")
155 #define dns_quietinit(...) \
156 DNS_PRAGMA_PUSH DNS_PRAGMA_QUIET __VA_ARGS__ DNS_PRAGMA_POP
157 #elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4
158 #define DNS_PRAGMA_PUSH _Pragma("GCC diagnostic push")
159 #define DNS_PRAGMA_QUIET _Pragma("GCC diagnostic ignored \"-Woverride-init\"")
160 #define DNS_PRAGMA_POP _Pragma("GCC diagnostic pop")
162 /* GCC parses the _Pragma operator less elegantly than clang. */
163 #define dns_quietinit(...) \
164 __extension__ ({ DNS_PRAGMA_PUSH DNS_PRAGMA_QUIET __VA_ARGS__; DNS_PRAGMA_POP })
166 #define DNS_PRAGMA_PUSH
167 #define DNS_PRAGMA_QUIET
168 #define DNS_PRAGMA_POP
169 #define dns_quietinit(...) __VA_ARGS__
173 #define DNS_PRAGMA_EXTENSION __extension__
175 #define DNS_PRAGMA_EXTENSION
180 * E V E N T S I N T E R F A C E S
182 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
185 #define DNS_POLLIN POLLIN
191 #define DNS_POLLOUT POLLOUT
193 #define DNS_POLLOUT 2
198 * See Application Interface below for configuring libevent bitmasks instead
199 * of poll(2) bitmasks.
202 #define DNS_EVWRITE 4
205 #define DNS_POLL2EV(set) \
206 (((set) & DNS_POLLIN)? DNS_EVREAD : 0) | (((set) & DNS_POLLOUT)? DNS_EVWRITE : 0)
208 #define DNS_EV2POLL(set) \
209 (((set) & DNS_EVREAD)? DNS_POLLIN : 0) | (((set) & DNS_EVWRITE)? DNS_POLLOUT : 0)
213 * E N U M E R A T I O N I N T E R F A C E S
215 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
219 #define DNS_S_QUESTION DNS_S_QD
222 #define DNS_S_ANSWER DNS_S_AN
225 #define DNS_S_AUTHORITY DNS_S_NS
228 #define DNS_S_ADDITIONAL DNS_S_AR
231 }; /* enum dns_section */
238 }; /* enum dns_class */
257 }; /* enum dns_type */
282 /* EDNS(0) extended RCODEs */
288 * NOTE: These string functions need a small buffer in case the literal
289 * integer value needs to be printed and returned. UNLESS this buffer is
290 * SPECIFIED, the returned string has ONLY BLOCK SCOPE.
292 #define DNS_STRMAXLEN 47 /* "QUESTION|ANSWER|AUTHORITY|ADDITIONAL" */
294 DNS_PUBLIC const char *dns_strsection(enum dns_section, void *, size_t);
295 #define dns_strsection3(a, b, c) \
296 dns_strsection((a), (b), (c))
297 #define dns_strsection1(a) dns_strsection((a), (char [DNS_STRMAXLEN + 1]){ 0 }, DNS_STRMAXLEN + 1)
298 #define dns_strsection(...) DNS_PP_CALL(DNS_PP_XPASTE(dns_strsection, DNS_PP_NARG(__VA_ARGS__)), __VA_ARGS__)
300 DNS_PUBLIC enum dns_section dns_isection(const char *);
302 DNS_PUBLIC const char *dns_strclass(enum dns_class, void *, size_t);
303 #define dns_strclass3(a, b, c) dns_strclass((a), (b), (c))
304 #define dns_strclass1(a) dns_strclass((a), (char [DNS_STRMAXLEN + 1]){ 0 }, DNS_STRMAXLEN + 1)
305 #define dns_strclass(...) DNS_PP_CALL(DNS_PP_XPASTE(dns_strclass, DNS_PP_NARG(__VA_ARGS__)), __VA_ARGS__)
307 DNS_PUBLIC enum dns_class dns_iclass(const char *);
309 DNS_PUBLIC const char *dns_strtype(enum dns_type, void *, size_t);
310 #define dns_strtype3(a, b, c) dns_strtype((a), (b), (c))
311 #define dns_strtype1(a) dns_strtype((a), (char [DNS_STRMAXLEN + 1]){ 0 }, DNS_STRMAXLEN + 1)
312 #define dns_strtype(...) DNS_PP_CALL(DNS_PP_XPASTE(dns_strtype, DNS_PP_NARG(__VA_ARGS__)), __VA_ARGS__)
314 DNS_PUBLIC enum dns_type dns_itype(const char *);
316 DNS_PUBLIC const char *dns_stropcode(enum dns_opcode);
318 DNS_PUBLIC enum dns_opcode dns_iopcode(const char *);
320 DNS_PUBLIC const char *dns_strrcode(enum dns_rcode);
322 DNS_PUBLIC enum dns_rcode dns_ircode(const char *);
326 * A T O M I C I N T E R F A C E S
328 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
330 typedef unsigned long dns_atomic_t;
332 typedef unsigned long dns_refcount_t; /* must be same value type as dns_atomic_t */
336 * C R Y P T O I N T E R F A C E S
338 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
340 typedef unsigned dns_random_f(void);
342 DNS_PUBLIC dns_random_f **dns_random_p(void);
344 #define dns_random (*dns_random_p()) /* was extern unsigned (*dns_random)(void) before 20160523 API */
348 * P A C K E T I N T E R F A C E
350 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
355 #if (defined BYTE_ORDER && BYTE_ORDER == BIG_ENDIAN) || (defined __sun && defined _BIG_ENDIAN)
381 }; /* struct dns_header */
383 #define dns_header(p) (&(p)->header)
386 #ifndef DNS_P_QBUFSIZ
387 #define DNS_P_QBUFSIZ dns_p_calcsize(256 + 4)
390 #ifndef DNS_P_DICTSIZE
391 #define DNS_P_DICTSIZE 16
395 unsigned short dict[DNS_P_DICTSIZE];
399 unsigned short base, end;
404 unsigned short maxudp;
409 struct { struct dns_packet *cqe_next, *cqe_prev; } cqe;
413 int:16; /* tcp padding */
415 DNS_PRAGMA_EXTENSION union {
416 struct dns_header header;
417 unsigned char data[1];
419 }; /* struct dns_packet */
421 #define dns_p_calcsize(n) (offsetof(struct dns_packet, data) + DNS_PP_MAX(12, (n)))
423 #define dns_p_sizeof(P) dns_p_calcsize((P)->end)
425 /** takes size of maximum desired payload */
426 #define dns_p_new(n) (dns_p_init((struct dns_packet *)&(union { unsigned char b[dns_p_calcsize((n))]; struct dns_packet p; }){ { 0 } }, dns_p_calcsize((n))))
428 /** takes size of entire packet structure as allocated */
429 DNS_PUBLIC struct dns_packet *dns_p_init(struct dns_packet *, size_t);
431 /** takes size of maximum desired payload */
432 DNS_PUBLIC struct dns_packet *dns_p_make(size_t, int *);
434 DNS_PUBLIC int dns_p_grow(struct dns_packet **);
436 DNS_PUBLIC struct dns_packet *dns_p_copy(struct dns_packet *, const struct dns_packet *);
438 #define dns_p_opcode(P) (dns_header(P)->opcode)
440 DNS_PUBLIC enum dns_rcode dns_p_rcode(struct dns_packet *);
442 DNS_PUBLIC unsigned dns_p_count(struct dns_packet *, enum dns_section);
444 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 *);
446 DNS_PUBLIC void dns_p_dictadd(struct dns_packet *, unsigned short);
448 DNS_PUBLIC struct dns_packet *dns_p_merge(struct dns_packet *, enum dns_section, struct dns_packet *, enum dns_section, int *);
450 DNS_PUBLIC void dns_p_dump(struct dns_packet *, FILE *);
452 DNS_PUBLIC int dns_p_study(struct dns_packet *);
456 * D O M A I N N A M E I N T E R F A C E S
458 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
460 #define DNS_D_MAXLABEL 63 /* + 1 '\0' */
461 #define DNS_D_MAXNAME 255 /* + 1 '\0' */
463 #define DNS_D_ANCHOR 1 /* anchor domain w/ root "." */
464 #define DNS_D_CLEAVE 2 /* cleave sub-domain */
465 #define DNS_D_TRIM 4 /* remove superfluous dots */
467 #define dns_d_new3(a, b, f) dns_d_init(&(char[DNS_D_MAXNAME + 1]){ 0 }, DNS_D_MAXNAME + 1, (a), (b), (f))
468 #define dns_d_new2(a, f) dns_d_new3((a), strlen((a)), (f))
469 #define dns_d_new1(a) dns_d_new3((a), strlen((a)), DNS_D_ANCHOR)
470 #define dns_d_new(...) DNS_PP_CALL(DNS_PP_XPASTE(dns_d_new, DNS_PP_NARG(__VA_ARGS__)), __VA_ARGS__)
472 DNS_PUBLIC char *dns_d_init(void *, size_t, const void *, size_t, int);
474 DNS_PUBLIC size_t dns_d_anchor(void *, size_t, const void *, size_t);
476 DNS_PUBLIC size_t dns_d_cleave(void *, size_t, const void *, size_t);
478 DNS_PUBLIC size_t dns_d_comp(void *, size_t, const void *, size_t, struct dns_packet *, int *);
480 DNS_PUBLIC size_t dns_d_expand(void *, size_t, unsigned short, struct dns_packet *, int *);
482 DNS_PUBLIC unsigned short dns_d_skip(unsigned short, struct dns_packet *);
484 DNS_PUBLIC int dns_d_push(struct dns_packet *, const void *, size_t);
486 DNS_PUBLIC size_t dns_d_cname(void *, size_t, const void *, size_t, struct dns_packet *, int *error);
490 * R E S O U R C E R E C O R D I N T E R F A C E S
492 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
495 enum dns_section section;
503 enum dns_class class;
510 }; /* struct dns_rr */
513 DNS_PUBLIC int dns_rr_copy(struct dns_packet *, struct dns_rr *, struct dns_packet *);
515 DNS_PUBLIC int dns_rr_parse(struct dns_rr *, unsigned short, struct dns_packet *);
517 DNS_PUBLIC unsigned short dns_rr_skip(unsigned short, struct dns_packet *);
519 DNS_PUBLIC int dns_rr_cmp(struct dns_rr *, struct dns_packet *, struct dns_rr *, struct dns_packet *);
521 DNS_PUBLIC size_t dns_rr_print(void *, size_t, struct dns_rr *, struct dns_packet *, int *);
524 #define dns_rr_i_new(P, ...) \
525 dns_rr_i_init(&dns_quietinit((struct dns_rr_i){ 0, __VA_ARGS__ }), (P))
528 enum dns_section section;
531 enum dns_class class;
536 int (*sort)(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
541 unsigned short count;
546 }; /* struct dns_rr_i */
548 DNS_PUBLIC int dns_rr_i_packet(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
550 DNS_PUBLIC int dns_rr_i_order(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
552 DNS_PUBLIC int dns_rr_i_shuffle(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
554 DNS_PUBLIC struct dns_rr_i *dns_rr_i_init(struct dns_rr_i *, struct dns_packet *);
556 #define dns_rr_i_save(i) ((i)->saved = (i)->state)
557 #define dns_rr_i_rewind(i) ((i)->state = (i)->saved)
558 #define dns_rr_i_count(i) ((i)->state.count)
560 DNS_PUBLIC unsigned dns_rr_grep(struct dns_rr *, unsigned, struct dns_rr_i *, struct dns_packet *, int *);
562 #define dns_rr_foreach_(rr, P, ...) \
563 for (struct dns_rr_i DNS_PP_XPASTE(i, __LINE__) = *dns_rr_i_new((P), __VA_ARGS__); dns_rr_grep((rr), 1, &DNS_PP_XPASTE(i, __LINE__), (P), &(int){ 0 }); )
565 #define dns_rr_foreach(...) dns_rr_foreach_(__VA_ARGS__)
569 * A R E S O U R C E R E C O R D
574 }; /* struct dns_a */
576 DNS_PUBLIC int dns_a_parse(struct dns_a *, struct dns_rr *, struct dns_packet *);
578 DNS_PUBLIC int dns_a_push(struct dns_packet *, struct dns_a *);
580 DNS_PUBLIC int dns_a_cmp(const struct dns_a *, const struct dns_a *);
582 DNS_PUBLIC size_t dns_a_print(void *, size_t, struct dns_a *);
584 DNS_PUBLIC size_t dns_a_arpa(void *, size_t, const struct dns_a *);
588 * AAAA R E S O U R C E R E C O R D
592 struct in6_addr addr;
593 }; /* struct dns_aaaa */
595 DNS_PUBLIC int dns_aaaa_parse(struct dns_aaaa *, struct dns_rr *, struct dns_packet *);
597 DNS_PUBLIC int dns_aaaa_push(struct dns_packet *, struct dns_aaaa *);
599 DNS_PUBLIC int dns_aaaa_cmp(const struct dns_aaaa *, const struct dns_aaaa *);
601 DNS_PUBLIC size_t dns_aaaa_print(void *, size_t, struct dns_aaaa *);
603 DNS_PUBLIC size_t dns_aaaa_arpa(void *, size_t, const struct dns_aaaa *);
607 * MX R E S O U R C E R E C O R D
611 unsigned short preference;
612 char host[DNS_D_MAXNAME + 1];
613 }; /* struct dns_mx */
615 DNS_PUBLIC int dns_mx_parse(struct dns_mx *, struct dns_rr *, struct dns_packet *);
617 DNS_PUBLIC int dns_mx_push(struct dns_packet *, struct dns_mx *);
619 DNS_PUBLIC int dns_mx_cmp(const struct dns_mx *, const struct dns_mx *);
621 DNS_PUBLIC size_t dns_mx_print(void *, size_t, struct dns_mx *);
623 DNS_PUBLIC size_t dns_mx_cname(void *, size_t, struct dns_mx *);
627 * NS R E S O U R C E R E C O R D
631 char host[DNS_D_MAXNAME + 1];
632 }; /* struct dns_ns */
634 DNS_PUBLIC int dns_ns_parse(struct dns_ns *, struct dns_rr *, struct dns_packet *);
636 DNS_PUBLIC int dns_ns_push(struct dns_packet *, struct dns_ns *);
638 DNS_PUBLIC int dns_ns_cmp(const struct dns_ns *, const struct dns_ns *);
640 DNS_PUBLIC size_t dns_ns_print(void *, size_t, struct dns_ns *);
642 DNS_PUBLIC size_t dns_ns_cname(void *, size_t, struct dns_ns *);
646 * CNAME R E S O U R C E R E C O R D
650 char host[DNS_D_MAXNAME + 1];
651 }; /* struct dns_cname */
653 DNS_PUBLIC int dns_cname_parse(struct dns_cname *, struct dns_rr *, struct dns_packet *);
655 DNS_PUBLIC int dns_cname_push(struct dns_packet *, struct dns_cname *);
657 DNS_PUBLIC int dns_cname_cmp(const struct dns_cname *, const struct dns_cname *);
659 DNS_PUBLIC size_t dns_cname_print(void *, size_t, struct dns_cname *);
661 DNS_PUBLIC size_t dns_cname_cname(void *, size_t, struct dns_cname *);
665 * SOA R E S O U R C E R E C O R D
669 char mname[DNS_D_MAXNAME + 1];
670 char rname[DNS_D_MAXNAME + 1];
671 unsigned serial, refresh, retry, expire, minimum;
672 }; /* struct dns_soa */
674 DNS_PUBLIC int dns_soa_parse(struct dns_soa *, struct dns_rr *, struct dns_packet *);
676 DNS_PUBLIC int dns_soa_push(struct dns_packet *, struct dns_soa *);
678 DNS_PUBLIC int dns_soa_cmp(const struct dns_soa *, const struct dns_soa *);
680 DNS_PUBLIC size_t dns_soa_print(void *, size_t, struct dns_soa *);
684 * PTR R E S O U R C E R E C O R D
688 char host[DNS_D_MAXNAME + 1];
689 }; /* struct dns_ptr */
691 DNS_PUBLIC int dns_ptr_parse(struct dns_ptr *, struct dns_rr *, struct dns_packet *);
693 DNS_PUBLIC int dns_ptr_push(struct dns_packet *, struct dns_ptr *);
695 DNS_PUBLIC int dns_ptr_cmp(const struct dns_ptr *, const struct dns_ptr *);
697 DNS_PUBLIC size_t dns_ptr_print(void *, size_t, struct dns_ptr *);
699 DNS_PUBLIC size_t dns_ptr_cname(void *, size_t, struct dns_ptr *);
701 DNS_PUBLIC size_t dns_ptr_qname(void *, size_t, int, void *);
705 * SRV R E S O U R C E R E C O R D
709 unsigned short priority;
710 unsigned short weight;
712 char target[DNS_D_MAXNAME + 1];
713 }; /* struct dns_srv */
715 DNS_PUBLIC int dns_srv_parse(struct dns_srv *, struct dns_rr *, struct dns_packet *);
717 DNS_PUBLIC int dns_srv_push(struct dns_packet *, struct dns_srv *);
719 DNS_PUBLIC int dns_srv_cmp(const struct dns_srv *, const struct dns_srv *);
721 DNS_PUBLIC size_t dns_srv_print(void *, size_t, struct dns_srv *);
723 DNS_PUBLIC size_t dns_srv_cname(void *, size_t, struct dns_srv *);
727 * OPT R E S O U R C E R E C O R D
730 #ifndef DNS_OPT_MINDATA
731 #define DNS_OPT_MINDATA 256
734 #define DNS_OPT_DNSSEC 0x8000
737 enum dns_rcode rcode;
738 unsigned char version;
739 unsigned short flags;
742 unsigned short maxsize; /* deprecated as confusing */
743 unsigned short maxudp; /* maximum UDP payload size */
747 unsigned char data[DNS_OPT_MINDATA];
748 }; /* struct dns_opt */
750 #define DNS_OPT_INIT(opt) { .size = sizeof (*opt) - offsetof(struct dns_opt, data) }
752 DNS_PUBLIC struct dns_opt *dns_opt_init(struct dns_opt *, size_t);
754 DNS_PUBLIC int dns_opt_parse(struct dns_opt *, struct dns_rr *, struct dns_packet *);
756 DNS_PUBLIC int dns_opt_push(struct dns_packet *, struct dns_opt *);
758 DNS_PUBLIC int dns_opt_cmp(const struct dns_opt *, const struct dns_opt *);
760 DNS_PUBLIC size_t dns_opt_print(void *, size_t, struct dns_opt *);
762 DNS_PUBLIC unsigned int dns_opt_ttl(const struct dns_opt *);
764 DNS_PUBLIC unsigned short dns_opt_class(const struct dns_opt *);
766 DNS_PUBLIC dns_error_t dns_opt_data_push(struct dns_opt *, unsigned char, unsigned short, const void *);
770 * SSHFP R E S O U R C E R E C O R D
779 enum dns_sshfp_digest {
784 unsigned char sha1[20];
786 }; /* struct dns_sshfp */
788 DNS_PUBLIC int dns_sshfp_parse(struct dns_sshfp *, struct dns_rr *, struct dns_packet *);
790 DNS_PUBLIC int dns_sshfp_push(struct dns_packet *, struct dns_sshfp *);
792 DNS_PUBLIC int dns_sshfp_cmp(const struct dns_sshfp *, const struct dns_sshfp *);
794 DNS_PUBLIC size_t dns_sshfp_print(void *, size_t, struct dns_sshfp *);
798 * TXT R E S O U R C E R E C O R D
801 #ifndef DNS_TXT_MINDATA
802 #define DNS_TXT_MINDATA 1024
807 unsigned char data[DNS_TXT_MINDATA];
808 }; /* struct dns_txt */
810 DNS_PUBLIC struct dns_txt *dns_txt_init(struct dns_txt *, size_t);
812 DNS_PUBLIC int dns_txt_parse(struct dns_txt *, struct dns_rr *, struct dns_packet *);
814 DNS_PUBLIC int dns_txt_push(struct dns_packet *, struct dns_txt *);
816 DNS_PUBLIC int dns_txt_cmp(const struct dns_txt *, const struct dns_txt *);
818 DNS_PUBLIC size_t dns_txt_print(void *, size_t, struct dns_txt *);
822 * ANY R E S O U R C E R E C O R D
827 struct dns_aaaa aaaa;
830 struct dns_cname cname;
835 struct dns_sshfp sshfp;
836 struct dns_txt txt, spf, rdata;
837 }; /* union dns_any */
839 #define DNS_ANY_INIT(any) { .rdata = { .size = sizeof *(any) - offsetof(struct dns_txt, data) } }
841 DNS_PUBLIC union dns_any *dns_any_init(union dns_any *, size_t);
843 DNS_PUBLIC int dns_any_parse(union dns_any *, struct dns_rr *, struct dns_packet *);
845 DNS_PUBLIC int dns_any_push(struct dns_packet *, union dns_any *, enum dns_type);
847 DNS_PUBLIC int dns_any_cmp(const union dns_any *, enum dns_type, const union dns_any *, enum dns_type);
849 DNS_PUBLIC size_t dns_any_print(void *, size_t, union dns_any *, enum dns_type);
851 DNS_PUBLIC size_t dns_any_cname(void *, size_t, union dns_any *, enum dns_type);
855 * H O S T S I N T E R F A C E
857 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
861 DNS_PUBLIC struct dns_hosts *dns_hosts_open(int *);
863 DNS_PUBLIC void dns_hosts_close(struct dns_hosts *);
865 DNS_PUBLIC dns_refcount_t dns_hosts_acquire(struct dns_hosts *);
867 DNS_PUBLIC dns_refcount_t dns_hosts_release(struct dns_hosts *);
869 DNS_PUBLIC struct dns_hosts *dns_hosts_mortal(struct dns_hosts *);
871 DNS_PUBLIC struct dns_hosts *dns_hosts_local(int *);
873 DNS_PUBLIC int dns_hosts_loadfile(struct dns_hosts *, FILE *);
875 DNS_PUBLIC int dns_hosts_loadpath(struct dns_hosts *, const char *);
877 DNS_PUBLIC int dns_hosts_dump(struct dns_hosts *, FILE *);
879 DNS_PUBLIC int dns_hosts_insert(struct dns_hosts *, int, const void *, const void *, _Bool);
881 DNS_PUBLIC struct dns_packet *dns_hosts_query(struct dns_hosts *, struct dns_packet *, int *);
885 * R E S O L V . C O N F I N T E R F A C E
887 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
889 struct dns_resolv_conf {
890 struct sockaddr_storage nameserver[3];
892 char search[4][DNS_D_MAXNAME + 1];
894 /* (f)ile, (b)ind, (c)ache */
895 char lookup[4 * (1 + (4 * 2))];
897 /* getaddrinfo family by preference order ("inet4", "inet6") */
916 DNS_RESCONF_TCP_ENABLE,
917 DNS_RESCONF_TCP_ONLY,
918 DNS_RESCONF_TCP_SOCKS,
919 DNS_RESCONF_TCP_DISABLE,
923 struct sockaddr_storage iface;
925 struct { /* PRIVATE */
926 dns_atomic_t refcount;
928 }; /* struct dns_resolv_conf */
930 DNS_PUBLIC struct dns_resolv_conf *dns_resconf_open(int *);
932 DNS_PUBLIC void dns_resconf_close(struct dns_resolv_conf *);
934 DNS_PUBLIC dns_refcount_t dns_resconf_acquire(struct dns_resolv_conf *);
936 DNS_PUBLIC dns_refcount_t dns_resconf_release(struct dns_resolv_conf *);
938 DNS_PUBLIC struct dns_resolv_conf *dns_resconf_mortal(struct dns_resolv_conf *);
940 DNS_PUBLIC struct dns_resolv_conf *dns_resconf_local(int *);
942 DNS_PUBLIC struct dns_resolv_conf *dns_resconf_root(int *);
944 DNS_PUBLIC int dns_resconf_pton(struct sockaddr_storage *, const char *);
946 DNS_PUBLIC int dns_resconf_loadfile(struct dns_resolv_conf *, FILE *);
948 DNS_PUBLIC int dns_resconf_loadpath(struct dns_resolv_conf *, const char *);
950 DNS_PUBLIC int dns_nssconf_loadfile(struct dns_resolv_conf *, FILE *);
952 DNS_PUBLIC int dns_nssconf_loadpath(struct dns_resolv_conf *, const char *);
954 DNS_PUBLIC int dns_resconf_dump(struct dns_resolv_conf *, FILE *);
956 DNS_PUBLIC int dns_nssconf_dump(struct dns_resolv_conf *, FILE *);
958 DNS_PUBLIC int dns_resconf_setiface(struct dns_resolv_conf *, const char *, unsigned short);
960 typedef unsigned long dns_resconf_i_t;
962 DNS_PUBLIC size_t dns_resconf_search(void *, size_t, const void *, size_t, struct dns_resolv_conf *, dns_resconf_i_t *);
966 * H I N T S E R V E R I N T E R F A C E
968 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
972 DNS_PUBLIC struct dns_hints *dns_hints_open(struct dns_resolv_conf *, int *);
974 DNS_PUBLIC void dns_hints_close(struct dns_hints *);
976 DNS_PUBLIC dns_refcount_t dns_hints_acquire(struct dns_hints *);
978 DNS_PUBLIC dns_refcount_t dns_hints_release(struct dns_hints *);
980 DNS_PUBLIC struct dns_hints *dns_hints_mortal(struct dns_hints *);
982 DNS_PUBLIC int dns_hints_insert(struct dns_hints *, const char *, const struct sockaddr *, unsigned);
984 DNS_PUBLIC unsigned dns_hints_insert_resconf(struct dns_hints *, const char *, const struct dns_resolv_conf *, int *);
986 DNS_PUBLIC struct dns_hints *dns_hints_local(struct dns_resolv_conf *, int *);
988 DNS_PUBLIC struct dns_hints *dns_hints_root(struct dns_resolv_conf *, int *);
990 DNS_PUBLIC struct dns_packet *dns_hints_query(struct dns_hints *, struct dns_packet *, int *);
992 DNS_PUBLIC int dns_hints_dump(struct dns_hints *, FILE *);
1002 }; /* struct dns_hints_i */
1004 #define dns_hints_i_new(...) (&(struct dns_hints_i){ __VA_ARGS__ })
1006 DNS_PUBLIC unsigned dns_hints_grep(struct sockaddr **, socklen_t *, unsigned, struct dns_hints_i *, struct dns_hints *);
1010 * C A C H E I N T E R F A C E
1012 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1017 dns_refcount_t (*acquire)(struct dns_cache *);
1018 dns_refcount_t (*release)(struct dns_cache *);
1020 struct dns_packet *(*query)(struct dns_packet *, struct dns_cache *, int *);
1022 int (*submit)(struct dns_packet *, struct dns_cache *);
1023 int (*check)(struct dns_cache *);
1024 struct dns_packet *(*fetch)(struct dns_cache *, int *);
1026 int (*pollfd)(struct dns_cache *);
1027 short (*events)(struct dns_cache *);
1028 void (*clear)(struct dns_cache *);
1035 struct { /* PRIVATE */
1036 dns_atomic_t refcount;
1038 }; /* struct dns_cache */
1041 DNS_PUBLIC struct dns_cache *dns_cache_init(struct dns_cache *);
1043 DNS_PUBLIC void dns_cache_close(struct dns_cache *);
1047 * A P P L I C A T I O N I N T E R F A C E
1049 * Options to change the behavior of the API. Applies across all the
1050 * different components.
1052 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1054 #define DNS_OPTS_INITIALIZER_ { 0, 0 }, 0, 0
1055 #define DNS_OPTS_INITIALIZER { DNS_OPTS_INITIALIZER_ }
1056 #define DNS_OPTS_INIT(...) { DNS_OPTS_INITIALIZER_, __VA_ARGS__ }
1058 #define dns_opts(...) (&dns_quietinit((struct dns_options)DNS_OPTS_INIT(__VA_ARGS__)))
1060 struct dns_options {
1062 * If the callback closes *fd, it must set it to -1. Otherwise, the
1063 * descriptor is queued and lazily closed at object destruction or
1064 * by an explicit call to _clear(). This allows safe use of
1065 * kqueue(2), epoll(2), et al -style persistent events.
1069 int (*cb)(int *fd, void *arg);
1072 /* bitmask for _events() routines */
1078 /* Use this SOCKS server. */
1079 const struct sockaddr_storage *socks_host;
1081 /* Credentials for the SOCKS server (optional). */
1082 const char *socks_user;
1083 const char *socks_password;
1084 }; /* struct dns_options */
1088 * S T A T S I N T E R F A C E S
1090 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1097 size_t count, bytes;
1100 }; /* struct dns_stat */
1104 * S O C K E T I N T E R F A C E
1106 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1110 DNS_PUBLIC struct dns_socket *dns_so_open(const struct sockaddr *, int, const struct dns_options *, int *error);
1112 DNS_PUBLIC void dns_so_close(struct dns_socket *);
1114 DNS_PUBLIC void dns_so_reset(struct dns_socket *);
1116 DNS_PUBLIC unsigned short dns_so_mkqid(struct dns_socket *so);
1118 DNS_PUBLIC struct dns_packet *dns_so_query(struct dns_socket *, struct dns_packet *, struct sockaddr *, int *);
1120 DNS_PUBLIC int dns_so_submit(struct dns_socket *, struct dns_packet *, struct sockaddr *);
1122 DNS_PUBLIC int dns_so_check(struct dns_socket *);
1124 DNS_PUBLIC struct dns_packet *dns_so_fetch(struct dns_socket *, int *);
1126 DNS_PUBLIC time_t dns_so_elapsed(struct dns_socket *);
1128 DNS_PUBLIC void dns_so_clear(struct dns_socket *);
1130 DNS_PUBLIC int dns_so_events(struct dns_socket *);
1132 DNS_PUBLIC int dns_so_pollfd(struct dns_socket *);
1134 DNS_PUBLIC int dns_so_poll(struct dns_socket *, int);
1136 DNS_PUBLIC const struct dns_stat *dns_so_stat(struct dns_socket *);
1138 DNS_PUBLIC struct dns_trace *dns_so_trace(struct dns_socket *);
1140 DNS_PUBLIC void dns_so_settrace(struct dns_socket *, struct dns_trace *);
1144 * R E S O L V E R I N T E R F A C E
1146 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1148 struct dns_resolver;
1150 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 *);
1152 DNS_PUBLIC struct dns_resolver *dns_res_stub(const struct dns_options *, int *);
1154 DNS_PUBLIC void dns_res_reset(struct dns_resolver *);
1156 DNS_PUBLIC void dns_res_close(struct dns_resolver *);
1158 DNS_PUBLIC dns_refcount_t dns_res_acquire(struct dns_resolver *);
1160 DNS_PUBLIC dns_refcount_t dns_res_release(struct dns_resolver *);
1162 DNS_PUBLIC struct dns_resolver *dns_res_mortal(struct dns_resolver *);
1164 DNS_PUBLIC int dns_res_submit(struct dns_resolver *, const char *, enum dns_type, enum dns_class);
1166 DNS_PUBLIC int dns_res_submit2(struct dns_resolver *, const char *, size_t, enum dns_type, enum dns_class);
1168 DNS_PUBLIC int dns_res_check(struct dns_resolver *);
1170 DNS_PUBLIC struct dns_packet *dns_res_fetch(struct dns_resolver *, int *);
1172 DNS_PUBLIC time_t dns_res_elapsed(struct dns_resolver *);
1174 DNS_PUBLIC void dns_res_clear(struct dns_resolver *);
1176 DNS_PUBLIC int dns_res_events(struct dns_resolver *);
1178 DNS_PUBLIC int dns_res_pollfd(struct dns_resolver *);
1180 DNS_PUBLIC time_t dns_res_timeout(struct dns_resolver *);
1182 DNS_PUBLIC int dns_res_poll(struct dns_resolver *, int);
1184 DNS_PUBLIC struct dns_packet *dns_res_query(struct dns_resolver *, const char *, enum dns_type, enum dns_class, int, int *);
1186 DNS_PUBLIC const struct dns_stat *dns_res_stat(struct dns_resolver *);
1188 DNS_PUBLIC void dns_res_sethints(struct dns_resolver *, struct dns_hints *);
1190 DNS_PUBLIC struct dns_trace *dns_res_trace(struct dns_resolver *);
1192 DNS_PUBLIC void dns_res_settrace(struct dns_resolver *, struct dns_trace *);
1196 * A D D R I N F O I N T E R F A C E
1198 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1200 struct dns_addrinfo;
1202 DNS_PUBLIC struct dns_addrinfo *dns_ai_open(const char *, const char *, enum dns_type, const struct addrinfo *, struct dns_resolver *, int *);
1204 DNS_PUBLIC void dns_ai_close(struct dns_addrinfo *);
1206 DNS_PUBLIC int dns_ai_nextent(struct addrinfo **, struct dns_addrinfo *);
1208 DNS_PUBLIC size_t dns_ai_print(void *, size_t, struct addrinfo *, struct dns_addrinfo *);
1210 DNS_PUBLIC time_t dns_ai_elapsed(struct dns_addrinfo *);
1212 DNS_PUBLIC void dns_ai_clear(struct dns_addrinfo *);
1214 DNS_PUBLIC int dns_ai_events(struct dns_addrinfo *);
1216 DNS_PUBLIC int dns_ai_pollfd(struct dns_addrinfo *);
1218 DNS_PUBLIC time_t dns_ai_timeout(struct dns_addrinfo *);
1220 DNS_PUBLIC int dns_ai_poll(struct dns_addrinfo *, int);
1222 DNS_PUBLIC const struct dns_stat *dns_ai_stat(struct dns_addrinfo *);
1224 DNS_PUBLIC struct dns_trace *dns_ai_trace(struct dns_addrinfo *);
1226 DNS_PUBLIC void dns_ai_settrace(struct dns_addrinfo *, struct dns_trace *);
1230 * Q U E R Y T R A C I N G I N T E R F A C E
1232 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1234 #define DNS_TRACE_ID_C(n) UINT64_C(n)
1235 typedef uint64_t dns_trace_id_t;
1237 #define DNS_TRACE_ABI 0x20160803
1239 struct dns_trace_event {
1241 DNS_TE_RES_SUBMIT = 1,
1242 DNS_TE_RES_FETCH = 99,
1244 DNS_TE_SO_SUBMIT = 100,
1246 DNS_TE_SO_FETCH = 199,
1248 DNS_TE_SYS_CONNECT = 200,
1260 char qname[DNS_D_MAXNAME + 1];
1261 enum dns_type qtype;
1262 enum dns_class qclass;
1271 struct sockaddr_storage haddr;
1272 char hname[DNS_D_MAXNAME + 1];
1285 struct sockaddr_storage src, dst;
1288 } sys_connect, sys_send, sys_recv;
1291 unsigned char data[];
1294 static inline size_t dns_te_datasize(const struct dns_trace_event *te) {
1295 size_t n = offsetof(struct dns_trace_event, data);
1296 return (n <= te->size)? te->size - n : 0;
1301 DNS_PUBLIC int dns_trace_abi(void);
1303 DNS_PUBLIC struct dns_trace *dns_trace_open(FILE *, dns_error_t *);
1305 DNS_PUBLIC void dns_trace_close(struct dns_trace *);
1307 DNS_PUBLIC dns_refcount_t dns_trace_acquire(struct dns_trace *);
1309 DNS_PUBLIC dns_refcount_t dns_trace_release(struct dns_trace *);
1311 DNS_PUBLIC dns_trace_id_t dns_trace_id(struct dns_trace *);
1313 DNS_PUBLIC dns_trace_id_t dns_trace_setid(struct dns_trace *, dns_trace_id_t);
1315 DNS_PUBLIC struct dns_trace_event *dns_trace_get(struct dns_trace *, struct dns_trace_event **, dns_error_t *);
1317 DNS_PUBLIC struct dns_trace_event *dns_trace_tag(struct dns_trace *, struct dns_trace_event *);
1319 DNS_PUBLIC dns_error_t dns_trace_put(struct dns_trace *, const struct dns_trace_event *, const void *, size_t);
1321 DNS_PUBLIC dns_error_t dns_trace_dump(struct dns_trace *, FILE *);
1323 DNS_PUBLIC struct dns_trace_event *dns_trace_fget(struct dns_trace_event **, FILE *, dns_error_t *);
1325 DNS_PUBLIC dns_error_t dns_trace_fput(const struct dns_trace_event *, const void *, size_t, FILE *);
1329 * U T I L I T Y I N T E R F A C E S
1331 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1333 DNS_PUBLIC size_t dns_strlcpy(char *, const char *, size_t);
1335 DNS_PUBLIC size_t dns_strlcat(char *, const char *, size_t);
1339 * M A C R O M A G I C S
1341 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1343 #define DNS_PP_MIN(a, b) (((a) < (b))? (a) : (b))
1344 #define DNS_PP_MAX(a, b) (((a) > (b))? (a) : (b))
1345 #define DNS_PP_NARG_(a, b, c, d, e, f, g, h, i, j, k, N,...) N
1346 #define DNS_PP_NARG(...) DNS_PP_NARG_(__VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
1347 #define DNS_PP_CALL(F, ...) F(__VA_ARGS__)
1348 #define DNS_PP_PASTE(x, y) x##y
1349 #define DNS_PP_XPASTE(x, y) DNS_PP_PASTE(x, y)
1350 #define DNS_PP_STRINGIFY_(s) #s
1351 #define DNS_PP_STRINGIFY(s) DNS_PP_STRINGIFY_(s)
1361 #define DNS_PP_D10 9
1362 #define DNS_PP_D11 10
1363 #define DNS_PP_DEC(N) DNS_PP_XPASTE(DNS_PP_D, N)