1 /* ==========================================================================
2 * dns.h - Recursive, Reentrant DNS Resolver.
3 * --------------------------------------------------------------------------
4 * Copyright (c) 2009, 2010 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 <stdio.h> /* FILE */
32 #include <string.h> /* strlen(3) */
34 #include <time.h> /* time_t */
40 #include <sys/types.h> /* socklen_t */
41 #include <sys/socket.h> /* struct socket */
43 #include <poll.h> /* POLLIN POLLOUT */
45 #include <netinet/in.h> /* struct in_addr struct in6_addr */
47 #include <netdb.h> /* struct addrinfo */
54 * Vendor: Entity for which versions numbers are relevant. (If forking
55 * change DNS_VENDOR to avoid confusion.)
59 * REL Official "release"--bug fixes, new features, etc.
60 * ABI Changes to existing object sizes or parameter types.
61 * API Changes that might effect application source.
63 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
65 #define DNS_VENDOR "william@25thandClement.com"
67 #define DNS_V_REL 0x20110117
68 #define DNS_V_ABI 0x20100709
69 #define DNS_V_API 0x20100709
72 const char *dns_vendor(void);
82 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
85 DNS_ENOBUFS = -(('d' << 24) | ('n' << 16) | ('s' << 8) | 64),
92 const char *dns_strerror(int);
98 * E V E N T S I N T E R F A C E S
100 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
103 #define DNS_POLLIN POLLIN
109 #define DNS_POLLOUT POLLOUT
111 #define DNS_POLLOUT 2
116 * See Application Interface below for configuring libevent bitmasks instead
117 * of poll(2) bitmasks.
120 #define DNS_EVWRITE 4
123 #define DNS_POLL2EV(set) \
124 (((set) & DNS_POLLIN)? DNS_EVREAD : 0) | (((set) & DNS_POLLOUT)? DNS_EVWRITE : 0)
126 #define DNS_EV2POLL(set) \
127 (((set) & DNS_EVREAD)? DNS_POLLIN : 0) | (((set) & DNS_EVWRITE)? DNS_POLLOUT : 0)
131 * E N U M E R A T I O N I N T E R F A C E S
133 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
137 #define DNS_S_QUESTION DNS_S_QD
140 #define DNS_S_ANSWER DNS_S_AN
143 #define DNS_S_AUTHORITY DNS_S_NS
146 #define DNS_S_ADDITIONAL DNS_S_AR
149 }; /* enum dns_section */
156 }; /* enum dns_class */
173 }; /* enum dns_type */
201 * NOTE: These string functions need a small buffer in case the literal
202 * integer value needs to be printed and returned. UNLESS this buffer is
203 * SPECIFIED, the returned string has ONLY BLOCK SCOPE.
205 #define DNS_STRMAXLEN 47 /* "QUESTION|ANSWER|AUTHORITY|ADDITIONAL" */
207 const char *dns_strsection(enum dns_section, void *, size_t);
208 #define dns_strsection3(a, b, c) \
209 dns_strsection((a), (b), (c))
210 #define dns_strsection1(a) dns_strsection((a), (char [DNS_STRMAXLEN + 1]){ 0 }, DNS_STRMAXLEN + 1)
211 #define dns_strsection(...) DNS_PP_CALL(DNS_PP_XPASTE(dns_strsection, DNS_PP_NARG(__VA_ARGS__)), __VA_ARGS__)
213 enum dns_section dns_isection(const char *);
215 const char *dns_strclass(enum dns_class, void *, size_t);
216 #define dns_strclass3(a, b, c) dns_strclass((a), (b), (c))
217 #define dns_strclass1(a) dns_strclass((a), (char [DNS_STRMAXLEN + 1]){ 0 }, DNS_STRMAXLEN + 1)
218 #define dns_strclass(...) DNS_PP_CALL(DNS_PP_XPASTE(dns_strclass, DNS_PP_NARG(__VA_ARGS__)), __VA_ARGS__)
220 enum dns_class dns_iclass(const char *);
222 const char *dns_strtype(enum dns_type, void *, size_t);
223 #define dns_strtype3(a, b, c) dns_strtype((a), (b), (c))
224 #define dns_strtype1(a) dns_strtype((a), (char [DNS_STRMAXLEN + 1]){ 0 }, DNS_STRMAXLEN + 1)
225 #define dns_strtype(...) DNS_PP_CALL(DNS_PP_XPASTE(dns_strtype, DNS_PP_NARG(__VA_ARGS__)), __VA_ARGS__)
227 enum dns_type dns_itype(const char *);
229 const char *dns_stropcode(enum dns_opcode);
231 enum dns_opcode dns_iopcode(const char *);
233 const char *dns_strrcode(enum dns_rcode);
235 enum dns_rcode dns_ircode(const char *);
239 * A T O M I C I N T E R F A C E S
241 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
243 typedef unsigned long dns_atomic_t;
247 * C R Y P T O I N T E R F A C E S
249 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
251 extern unsigned (*dns_random)(void);
255 * P A C K E T I N T E R F A C E
257 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
262 #if BYTE_ORDER == BIG_ENDIAN
288 }; /* struct dns_header */
290 #define dns_header(p) (&(p)->header)
293 #ifndef DNS_P_QBUFSIZ
294 #define DNS_P_QBUFSIZ dns_p_calcsize(256 + 4)
297 #ifndef DNS_P_DICTSIZE
298 #define DNS_P_DICTSIZE 16
302 unsigned short dict[DNS_P_DICTSIZE];
305 unsigned short base, end;
308 struct { struct dns_packet *cqe_next, *cqe_prev; } cqe;
312 int:16; /* tcp padding */
315 struct dns_header header;
316 unsigned char data[1];
318 }; /* struct dns_packet */
320 #define dns_p_calcsize(n) (offsetof(struct dns_packet, data) + DNS_PP_MAX(12, (n)))
322 #define dns_p_sizeof(P) dns_p_calcsize((P)->end)
324 /** takes size of maximum desired payload */
325 #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))))
327 /** takes size of entire packet structure as allocated */
328 struct dns_packet *dns_p_init(struct dns_packet *, size_t);
330 /** takes size of maximum desired payload */
331 struct dns_packet *dns_p_make(size_t, int *);
333 int dns_p_grow(struct dns_packet **);
335 struct dns_packet *dns_p_copy(struct dns_packet *, const struct dns_packet *);
337 #define dns_p_opcode(P) (dns_header(P)->opcode)
339 #define dns_p_rcode(P) (dns_header(P)->rcode)
341 unsigned dns_p_count(struct dns_packet *, enum dns_section);
343 int dns_p_push(struct dns_packet *, enum dns_section, const void *, size_t, enum dns_type, enum dns_class, unsigned, const void *);
345 void dns_p_dictadd(struct dns_packet *, unsigned short);
347 struct dns_packet *dns_p_merge(struct dns_packet *, enum dns_section, struct dns_packet *, enum dns_section, int *);
349 void dns_p_dump(struct dns_packet *, FILE *);
351 int dns_p_study(struct dns_packet *);
355 * D O M A I N N A M E I N T E R F A C E S
357 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
359 #define DNS_D_MAXLABEL 63 /* + 1 '\0' */
360 #define DNS_D_MAXNAME 255 /* + 1 '\0' */
362 #define DNS_D_ANCHOR 1 /* anchor domain w/ root "." */
363 #define DNS_D_CLEAVE 2 /* cleave sub-domain */
364 #define DNS_D_TRIM 4 /* remove superfluous dots */
366 #define dns_d_new3(a, b, f) dns_d_init(&(char[DNS_D_MAXNAME + 1]){ 0 }, DNS_D_MAXNAME + 1, (a), (b), (f))
367 #define dns_d_new2(a, f) dns_d_new3((a), strlen((a)), (f))
368 #define dns_d_new1(a) dns_d_new3((a), strlen((a)), DNS_D_ANCHOR)
369 #define dns_d_new(...) DNS_PP_CALL(DNS_PP_XPASTE(dns_d_new, DNS_PP_NARG(__VA_ARGS__)), __VA_ARGS__)
371 char *dns_d_init(void *, size_t, const void *, size_t, int);
373 size_t dns_d_anchor(void *, size_t, const void *, size_t);
375 size_t dns_d_cleave(void *, size_t, const void *, size_t);
377 size_t dns_d_comp(void *, size_t, const void *, size_t, struct dns_packet *, int *);
379 size_t dns_d_expand(void *, size_t, unsigned short, struct dns_packet *, int *);
381 unsigned short dns_d_skip(unsigned short, struct dns_packet *);
383 int dns_d_push(struct dns_packet *, const void *, size_t);
385 size_t dns_d_cname(void *, size_t, const void *, size_t, struct dns_packet *, int *error);
389 * R E S O U R C E R E C O R D I N T E R F A C E S
391 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
394 enum dns_section section;
402 enum dns_class class;
409 }; /* struct dns_rr */
412 int dns_rr_copy(struct dns_packet *, struct dns_rr *, struct dns_packet *);
414 int dns_rr_parse(struct dns_rr *, unsigned short, struct dns_packet *);
416 unsigned short dns_rr_skip(unsigned short, struct dns_packet *);
418 int dns_rr_cmp(struct dns_rr *, struct dns_packet *, struct dns_rr *, struct dns_packet *);
420 size_t dns_rr_print(void *, size_t, struct dns_rr *, struct dns_packet *, int *);
423 #define dns_rr_i_new(P, ...) dns_rr_i_init(&(struct dns_rr_i){ 0, __VA_ARGS__ }, (P))
426 enum dns_section section;
429 enum dns_class class;
439 unsigned short count;
444 }; /* struct dns_rr_i */
446 int dns_rr_i_packet(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
448 int dns_rr_i_order(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
450 int dns_rr_i_shuffle(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
452 struct dns_rr_i *dns_rr_i_init(struct dns_rr_i *, struct dns_packet *);
454 #define dns_rr_i_save(i) ((i)->saved = (i)->state)
455 #define dns_rr_i_rewind(i) ((i)->state = (i)->saved)
456 #define dns_rr_i_count(i) ((i)->state.count)
458 unsigned dns_rr_grep(struct dns_rr *, unsigned, struct dns_rr_i *, struct dns_packet *, int *);
460 #define dns_rr_foreach_(rr, P, ...) \
461 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 }); )
463 #define dns_rr_foreach(...) dns_rr_foreach_(__VA_ARGS__)
467 * A R E S O U R C E R E C O R D
472 }; /* struct dns_a */
474 int dns_a_parse(struct dns_a *, struct dns_rr *, struct dns_packet *);
476 int dns_a_push(struct dns_packet *, struct dns_a *);
478 int dns_a_cmp(const struct dns_a *, const struct dns_a *);
480 size_t dns_a_print(void *, size_t, struct dns_a *);
484 * AAAA R E S O U R C E R E C O R D
488 struct in6_addr addr;
489 }; /* struct dns_aaaa */
491 int dns_aaaa_parse(struct dns_aaaa *, struct dns_rr *, struct dns_packet *);
493 int dns_aaaa_push(struct dns_packet *, struct dns_aaaa *);
495 int dns_aaaa_cmp(const struct dns_aaaa *, const struct dns_aaaa *);
497 size_t dns_aaaa_print(void *, size_t, struct dns_aaaa *);
501 * MX R E S O U R C E R E C O R D
505 unsigned short preference;
506 char host[DNS_D_MAXNAME + 1];
507 }; /* struct dns_mx */
509 int dns_mx_parse(struct dns_mx *, struct dns_rr *, struct dns_packet *);
511 int dns_mx_push(struct dns_packet *, struct dns_mx *);
513 int dns_mx_cmp(const struct dns_mx *, const struct dns_mx *);
515 size_t dns_mx_print(void *, size_t, struct dns_mx *);
517 size_t dns_mx_cname(void *, size_t, struct dns_mx *);
521 * NS R E S O U R C E R E C O R D
525 char host[DNS_D_MAXNAME + 1];
526 }; /* struct dns_ns */
528 int dns_ns_parse(struct dns_ns *, struct dns_rr *, struct dns_packet *);
530 int dns_ns_push(struct dns_packet *, struct dns_ns *);
532 int dns_ns_cmp(const struct dns_ns *, const struct dns_ns *);
534 size_t dns_ns_print(void *, size_t, struct dns_ns *);
536 size_t dns_ns_cname(void *, size_t, struct dns_ns *);
540 * CNAME R E S O U R C E R E C O R D
544 char host[DNS_D_MAXNAME + 1];
545 }; /* struct dns_cname */
547 int dns_cname_parse(struct dns_cname *, struct dns_rr *, struct dns_packet *);
549 int dns_cname_push(struct dns_packet *, struct dns_cname *);
551 int dns_cname_cmp(const struct dns_cname *, const struct dns_cname *);
553 size_t dns_cname_print(void *, size_t, struct dns_cname *);
555 size_t dns_cname_cname(void *, size_t, struct dns_cname *);
559 * SOA R E S O U R C E R E C O R D
563 char mname[DNS_D_MAXNAME + 1];
564 char rname[DNS_D_MAXNAME + 1];
565 unsigned serial, refresh, retry, expire, minimum;
566 }; /* struct dns_soa */
568 int dns_soa_parse(struct dns_soa *, struct dns_rr *, struct dns_packet *);
570 int dns_soa_push(struct dns_packet *, struct dns_soa *);
572 int dns_soa_cmp(const struct dns_soa *, const struct dns_soa *);
574 size_t dns_soa_print(void *, size_t, struct dns_soa *);
578 * PTR R E S O U R C E R E C O R D
582 char host[DNS_D_MAXNAME + 1];
583 }; /* struct dns_ptr */
585 int dns_ptr_parse(struct dns_ptr *, struct dns_rr *, struct dns_packet *);
587 int dns_ptr_push(struct dns_packet *, struct dns_ptr *);
589 int dns_ptr_cmp(const struct dns_ptr *, const struct dns_ptr *);
591 size_t dns_ptr_print(void *, size_t, struct dns_ptr *);
593 size_t dns_ptr_cname(void *, size_t, struct dns_ptr *);
597 * SRV R E S O U R C E R E C O R D
601 unsigned short priority;
602 unsigned short weight;
604 char target[DNS_D_MAXNAME + 1];
605 }; /* struct dns_srv */
607 int dns_srv_parse(struct dns_srv *, struct dns_rr *, struct dns_packet *);
609 int dns_srv_push(struct dns_packet *, struct dns_srv *);
611 int dns_srv_cmp(const struct dns_srv *, const struct dns_srv *);
613 size_t dns_srv_print(void *, size_t, struct dns_srv *);
615 size_t dns_srv_cname(void *, size_t, struct dns_srv *);
619 * SSHFP R E S O U R C E R E C O R D
628 enum dns_sshfp_digest {
633 unsigned char sha1[20];
635 }; /* struct dns_sshfp */
637 int dns_sshfp_parse(struct dns_sshfp *, struct dns_rr *, struct dns_packet *);
639 int dns_sshfp_push(struct dns_packet *, struct dns_sshfp *);
641 int dns_sshfp_cmp(const struct dns_sshfp *, const struct dns_sshfp *);
643 size_t dns_sshfp_print(void *, size_t, struct dns_sshfp *);
647 * TXT R E S O U R C E R E C O R D
650 #ifndef DNS_TXT_MINDATA
651 #define DNS_TXT_MINDATA 1024
656 unsigned char data[DNS_TXT_MINDATA];
657 }; /* struct dns_txt */
659 struct dns_txt *dns_txt_init(struct dns_txt *, size_t);
661 int dns_txt_parse(struct dns_txt *, struct dns_rr *, struct dns_packet *);
663 int dns_txt_push(struct dns_packet *, struct dns_txt *);
665 int dns_txt_cmp(const struct dns_txt *, const struct dns_txt *);
667 size_t dns_txt_print(void *, size_t, struct dns_txt *);
671 * ANY R E S O U R C E R E C O R D
676 struct dns_aaaa aaaa;
679 struct dns_cname cname;
683 struct dns_sshfp sshfp;
684 struct dns_txt txt, spf, rdata;
685 }; /* union dns_any */
687 #define DNS_ANY_INIT(any) { .rdata = { .size = sizeof *(any) } }
689 union dns_any *dns_any_init(union dns_any *, size_t);
691 int dns_any_parse(union dns_any *, struct dns_rr *, struct dns_packet *);
693 int dns_any_push(struct dns_packet *, union dns_any *, enum dns_type);
695 int dns_any_cmp(const union dns_any *, enum dns_type, const union dns_any *, enum dns_type);
697 size_t dns_any_print(void *, size_t, union dns_any *, enum dns_type);
699 size_t dns_any_cname(void *, size_t, union dns_any *, enum dns_type);
703 * H O S T S I N T E R F A C E
705 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
709 struct dns_hosts *dns_hosts_open(int *);
711 void dns_hosts_close(struct dns_hosts *);
713 unsigned dns_hosts_acquire(struct dns_hosts *);
715 unsigned dns_hosts_release(struct dns_hosts *);
717 struct dns_hosts *dns_hosts_mortal(struct dns_hosts *);
719 struct dns_hosts *dns_hosts_local(int *);
721 int dns_hosts_loadfile(struct dns_hosts *, FILE *);
723 int dns_hosts_loadpath(struct dns_hosts *, const char *);
725 int dns_hosts_dump(struct dns_hosts *, FILE *);
727 int dns_hosts_insert(struct dns_hosts *, int, const void *, const void *, _Bool);
729 struct dns_packet *dns_hosts_query(struct dns_hosts *, struct dns_packet *, int *);
733 * R E S O L V . C O N F I N T E R F A C E
735 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
737 struct dns_resolv_conf {
738 struct sockaddr_storage nameserver[3];
740 char search[4][DNS_D_MAXNAME + 1];
742 /* (f)ile, (b)ind, (c)ache */
761 DNS_RESCONF_TCP_ENABLE,
762 DNS_RESCONF_TCP_ONLY,
763 DNS_RESCONF_TCP_DISABLE,
767 struct sockaddr_storage iface;
769 struct { /* PRIVATE */
770 dns_atomic_t refcount;
772 }; /* struct dns_resolv_conf */
774 struct dns_resolv_conf *dns_resconf_open(int *);
776 void dns_resconf_close(struct dns_resolv_conf *);
778 unsigned dns_resconf_acquire(struct dns_resolv_conf *);
780 unsigned dns_resconf_release(struct dns_resolv_conf *);
782 struct dns_resolv_conf *dns_resconf_mortal(struct dns_resolv_conf *);
784 struct dns_resolv_conf *dns_resconf_local(int *);
786 struct dns_resolv_conf *dns_resconf_root(int *);
788 int dns_resconf_loadfile(struct dns_resolv_conf *, FILE *);
790 int dns_resconf_loadpath(struct dns_resolv_conf *, const char *);
792 int dns_resconf_dump(struct dns_resolv_conf *, FILE *);
794 int dns_resconf_setiface(struct dns_resolv_conf *, const char *, unsigned short);
796 typedef unsigned long dns_resconf_i_t;
798 size_t dns_resconf_search(void *, size_t, const void *, size_t, struct dns_resolv_conf *, dns_resconf_i_t *);
802 * H I N T S E R V E R I N T E R F A C E
804 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
808 struct dns_hints *dns_hints_open(struct dns_resolv_conf *, int *);
810 void dns_hints_close(struct dns_hints *);
812 unsigned dns_hints_acquire(struct dns_hints *);
814 unsigned dns_hints_release(struct dns_hints *);
816 struct dns_hints *dns_hints_mortal(struct dns_hints *);
818 int dns_hints_insert(struct dns_hints *, const char *, const struct sockaddr *, unsigned);
820 unsigned dns_hints_insert_resconf(struct dns_hints *, const char *, const struct dns_resolv_conf *, int *);
822 struct dns_hints *dns_hints_local(struct dns_resolv_conf *, int *);
824 struct dns_hints *dns_hints_root(struct dns_resolv_conf *, int *);
834 }; /* struct dns_hints_i */
836 #define dns_hints_i_new(...) (&(struct dns_hints_i){ __VA_ARGS__ })
838 unsigned dns_hints_grep(struct sockaddr **, socklen_t *, unsigned, struct dns_hints_i *, struct dns_hints *);
842 * C A C H E I N T E R F A C E
844 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
849 dns_atomic_t (*acquire)(struct dns_cache *);
850 dns_atomic_t (*release)(struct dns_cache *);
852 struct dns_packet *(*query)(struct dns_packet *, struct dns_cache *, int *);
854 int (*submit)(struct dns_packet *, struct dns_cache *);
855 int (*check)(struct dns_cache *);
856 struct dns_packet *(*fetch)(struct dns_cache *, int *);
858 int (*pollfd)(struct dns_cache *);
859 short (*events)(struct dns_cache *);
860 void (*clear)(struct dns_cache *);
866 }; /* struct dns_cache */
869 struct dns_cache *dns_cache_init(struct dns_cache *);
871 void dns_cache_close(struct dns_cache *);
875 * A P P L I C A T I O N I N T E R F A C E
877 * Options to change the behavior of the API. Applies across all the
878 * different components.
880 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
882 #define DNS_OPTS_INITIALIZER_ { 0, 0 }, 0
883 #define DNS_OPTS_INITIALIZER { DNS_OPTS_INITIALIZER_ }
884 #define DNS_OPTS_INIT(...) { DNS_OPTS_INITIALIZER_, __VA_ARGS__ }
886 #define dns_opts(...) (&(struct dns_options)DNS_OPTS_INIT(__VA_ARGS__))
890 * If the callback closes *fd, it must set it to -1. Otherwise, the
891 * descriptor is queued and lazily closed at object destruction or
892 * by an explicit call to _clear(). This allows safe use of
893 * kqueue(2), epoll(2), et al -style persistent events.
897 int (*cb)(int *fd, void *arg);
900 /* bitmask for _events() routines */
905 }; /* struct dns_options */
909 * S T A T S I N T E R F A C E S
911 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
921 }; /* struct dns_stat */
925 * S O C K E T I N T E R F A C E
927 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
931 struct dns_socket *dns_so_open(const struct sockaddr *, int, const struct dns_options *, int *error);
933 void dns_so_close(struct dns_socket *);
935 void dns_so_reset(struct dns_socket *);
937 unsigned short dns_so_mkqid(struct dns_socket *so);
939 struct dns_packet *dns_so_query(struct dns_socket *, struct dns_packet *, struct sockaddr *, int *);
941 int dns_so_submit(struct dns_socket *, struct dns_packet *, struct sockaddr *);
943 int dns_so_check(struct dns_socket *);
945 struct dns_packet *dns_so_fetch(struct dns_socket *, int *);
947 time_t dns_so_elapsed(struct dns_socket *);
949 void dns_so_clear(struct dns_socket *);
951 int dns_so_events(struct dns_socket *);
953 int dns_so_pollfd(struct dns_socket *);
955 int dns_so_poll(struct dns_socket *, int);
957 const struct dns_stat *dns_so_stat(struct dns_socket *);
961 * R E S O L V E R I N T E R F A C E
963 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
967 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 *);
969 struct dns_resolver *dns_res_stub(const struct dns_options *, int *);
971 void dns_res_reset(struct dns_resolver *);
973 void dns_res_close(struct dns_resolver *);
975 unsigned dns_res_acquire(struct dns_resolver *);
977 unsigned dns_res_release(struct dns_resolver *);
979 struct dns_resolver *dns_res_mortal(struct dns_resolver *);
981 int dns_res_submit(struct dns_resolver *, const char *, enum dns_type, enum dns_class);
983 int dns_res_check(struct dns_resolver *);
985 struct dns_packet *dns_res_fetch(struct dns_resolver *, int *);
987 time_t dns_res_elapsed(struct dns_resolver *);
989 void dns_res_clear(struct dns_resolver *);
991 int dns_res_events(struct dns_resolver *);
993 int dns_res_pollfd(struct dns_resolver *);
995 int dns_res_poll(struct dns_resolver *, int);
997 struct dns_packet *dns_res_query(struct dns_resolver *, const char *, enum dns_type, enum dns_class, int, int *);
999 const struct dns_stat *dns_res_stat(struct dns_resolver *);
1003 * A D D R I N F O I N T E R F A C E
1005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1007 struct dns_addrinfo;
1009 struct dns_addrinfo *dns_ai_open(const char *, const char *, enum dns_type, const struct addrinfo *, struct dns_resolver *, int *);
1011 void dns_ai_close(struct dns_addrinfo *);
1013 int dns_ai_nextent(struct addrinfo **, struct dns_addrinfo *);
1015 size_t dns_ai_print(void *, size_t, struct addrinfo *, struct dns_addrinfo *);
1017 time_t dns_ai_elapsed(struct dns_addrinfo *);
1019 void dns_ai_clear(struct dns_addrinfo *);
1021 int dns_ai_events(struct dns_addrinfo *);
1023 int dns_ai_pollfd(struct dns_addrinfo *);
1025 int dns_ai_poll(struct dns_addrinfo *, int);
1027 const struct dns_stat *dns_ai_stat(struct dns_addrinfo *);
1029 void *dns_sa_addr(int af, void *sa);
1030 unsigned short *dns_sa_port(int af, void *sa);
1032 const char *dns_inet_ntop(int af, const void *src, void *dst, unsigned long lim);
1034 #define dns_inet_pton(...) inet_pton(__VA_ARGS__)
1035 #define dns_inet_ntop(...) inet_ntop(__VA_ARGS__)
1037 #define dns_sa_family(sa) (((struct sockaddr *)(sa))->sa_family)
1039 * U T I L I T Y I N T E R F A C E S
1041 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1043 size_t dns_strlcpy(char *, const char *, size_t);
1045 size_t dns_strlcat(char *, const char *, size_t);
1049 * M A C R O M A G I C S
1051 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1053 #define DNS_PP_MAX(a, b) (((a) > (b))? (a) : (b))
1054 #define DNS_PP_NARG_(a, b, c, d, e, f, g, h, i, j, k, N,...) N
1055 #define DNS_PP_NARG(...) DNS_PP_NARG_(__VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
1056 #define DNS_PP_CALL(F, ...) F(__VA_ARGS__)
1057 #define DNS_PP_PASTE(x, y) x##y
1058 #define DNS_PP_XPASTE(x, y) DNS_PP_PASTE(x, y)
1059 #define DNS_PP_STRINGIFY_(s) #s
1060 #define DNS_PP_STRINGIFY(s) DNS_PP_STRINGIFY_(s)
1070 #define DNS_PP_D10 9
1071 #define DNS_PP_D11 10
1072 #define DNS_PP_DEC(N) DNS_PP_XPASTE(DNS_PP_D, N)