summaryrefslogtreecommitdiffstats
path: root/dirmngr/dns.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dirmngr/dns.h1321
1 files changed, 1321 insertions, 0 deletions
diff --git a/dirmngr/dns.h b/dirmngr/dns.h
new file mode 100644
index 0000000..1f647e1
--- /dev/null
+++ b/dirmngr/dns.h
@@ -0,0 +1,1321 @@
+/* ==========================================================================
+ * dns.h - Recursive, Reentrant DNS Resolver.
+ * --------------------------------------------------------------------------
+ * Copyright (c) 2009, 2010, 2012-2015 William Ahern
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ==========================================================================
+ */
+#ifndef DNS_H
+#define DNS_H
+
+#include <stddef.h> /* size_t offsetof() */
+#include <stdint.h> /* uint64_t */
+#include <stdio.h> /* FILE */
+#include <string.h> /* strlen(3) */
+#include <time.h> /* struct timespec time_t */
+
+#if _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/param.h> /* BYTE_ORDER BIG_ENDIAN _BIG_ENDIAN */
+#include <sys/types.h> /* socklen_t */
+#include <sys/socket.h> /* struct socket */
+#include <poll.h> /* POLLIN POLLOUT */
+#include <netinet/in.h> /* struct in_addr struct in6_addr */
+#include <netdb.h> /* struct addrinfo */
+#endif
+
+
+/*
+ * V I S I B I L I T Y
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef DNS_PUBLIC
+#define DNS_PUBLIC
+#endif
+
+
+/*
+ * V E R S I O N
+ *
+ * Vendor: Entity for which versions numbers are relevant. (If forking
+ * change DNS_VENDOR to avoid confusion.)
+ *
+ * Three versions:
+ *
+ * REL Official "release"--bug fixes, new features, etc.
+ * ABI Changes to existing object sizes or parameter types
+ * API Changes that might effect application source.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define DNS_VENDOR "william@25thandClement.com"
+
+#define DNS_V_REL 0x20160809
+#define DNS_V_ABI 0x20160608
+#define DNS_V_API 0x20160809
+
+
+DNS_PUBLIC const char *dns_vendor(void);
+
+DNS_PUBLIC int dns_v_rel(void);
+DNS_PUBLIC int dns_v_abi(void);
+DNS_PUBLIC int dns_v_api(void);
+
+
+/*
+ * E R R O R S
+ *
+ * Errors and exceptions are always returned through an int. This should
+ * hopefully make integration easier in the majority of circumstances, and
+ * also cut down on useless compiler warnings.
+ *
+ * System and library errors are returned together. POSIX guarantees that
+ * all system errors are positive integers. Library errors are always
+ * negative integers in the range DNS_EBASE to DNS_ELAST, with the high bits
+ * set to the three magic ASCII characters "dns".
+ *
+ * dns_strerror() returns static English string descriptions of all known
+ * errors, and punts the remainder to strerror(3).
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define DNS_EBASE -(('d' << 24) | ('n' << 16) | ('s' << 8) | 64)
+
+#define dns_error_t int /* for documentation only */
+
+enum dns_errno {
+ DNS_ENOBUFS = DNS_EBASE,
+ DNS_EILLEGAL,
+ DNS_EORDER,
+ DNS_ESECTION,
+ DNS_EUNKNOWN,
+ DNS_EADDRESS,
+ DNS_ENOQUERY,
+ DNS_ENOANSWER,
+ DNS_EFETCHED,
+ DNS_ESERVICE, /* EAI_SERVICE */
+ DNS_ENONAME, /* EAI_NONAME */
+ DNS_EFAIL, /* EAI_FAIL */
+ DNS_ECONNFIN,
+ DNS_EVERIFY,
+ DNS_ELAST,
+}; /* dns_errno */
+
+DNS_PUBLIC const char *dns_strerror(dns_error_t);
+
+DNS_PUBLIC int *dns_debug_p(void);
+
+#define dns_debug (*dns_debug_p()) /* was extern int dns_debug before 20160523 API */
+
+
+/*
+ * C O M P I L E R A N N O T A T I O N S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#if defined __clang__
+#define DNS_PRAGMA_PUSH _Pragma("clang diagnostic push")
+#define DNS_PRAGMA_QUIET _Pragma("clang diagnostic ignored \"-Winitializer-overrides\"")
+#define DNS_PRAGMA_POP _Pragma("clang diagnostic pop")
+
+#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4
+#define DNS_PRAGMA_PUSH _Pragma("GCC diagnostic push")
+#define DNS_PRAGMA_QUIET _Pragma("GCC diagnostic ignored \"-Woverride-init\"")
+#define DNS_PRAGMA_POP _Pragma("GCC diagnostic pop")
+
+#else
+#define DNS_PRAGMA_PUSH
+#define DNS_PRAGMA_QUIET
+#define DNS_PRAGMA_POP
+#endif
+
+#if defined __GNUC__
+#define DNS_PRAGMA_EXTENSION __extension__
+#else
+#define DNS_PRAGMA_EXTENSION
+#endif
+
+
+/*
+ * E V E N T S I N T E R F A C E S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#if defined(POLLIN)
+#define DNS_POLLIN POLLIN
+#else
+#define DNS_POLLIN 1
+#endif
+
+#if defined(POLLOUT)
+#define DNS_POLLOUT POLLOUT
+#else
+#define DNS_POLLOUT 2
+#endif
+
+
+/*
+ * See Application Interface below for configuring libevent bitmasks instead
+ * of poll(2) bitmasks.
+ */
+#define DNS_EVREAD 2
+#define DNS_EVWRITE 4
+
+
+#define DNS_POLL2EV(set) \
+ (((set) & DNS_POLLIN)? DNS_EVREAD : 0) | (((set) & DNS_POLLOUT)? DNS_EVWRITE : 0)
+
+#define DNS_EV2POLL(set) \
+ (((set) & DNS_EVREAD)? DNS_POLLIN : 0) | (((set) & DNS_EVWRITE)? DNS_POLLOUT : 0)
+
+
+/*
+ * E N U M E R A T I O N I N T E R F A C E S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+enum dns_section {
+ DNS_S_QD = 0x01,
+#define DNS_S_QUESTION DNS_S_QD
+
+ DNS_S_AN = 0x02,
+#define DNS_S_ANSWER DNS_S_AN
+
+ DNS_S_NS = 0x04,
+#define DNS_S_AUTHORITY DNS_S_NS
+
+ DNS_S_AR = 0x08,
+#define DNS_S_ADDITIONAL DNS_S_AR
+
+ DNS_S_ALL = 0x0f
+}; /* enum dns_section */
+
+
+enum dns_class {
+ DNS_C_IN = 1,
+
+ DNS_C_ANY = 255
+}; /* enum dns_class */
+
+
+enum dns_type {
+ DNS_T_A = 1,
+ DNS_T_NS = 2,
+ DNS_T_CNAME = 5,
+ DNS_T_SOA = 6,
+ DNS_T_PTR = 12,
+ DNS_T_MX = 15,
+ DNS_T_TXT = 16,
+ DNS_T_AAAA = 28,
+ DNS_T_SRV = 33,
+ DNS_T_OPT = 41,
+ DNS_T_SSHFP = 44,
+ DNS_T_SPF = 99,
+ DNS_T_AXFR = 252,
+
+ DNS_T_ALL = 255
+}; /* enum dns_type */
+
+
+enum dns_opcode {
+ DNS_OP_QUERY = 0,
+ DNS_OP_IQUERY = 1,
+ DNS_OP_STATUS = 2,
+ DNS_OP_NOTIFY = 4,
+ DNS_OP_UPDATE = 5,
+}; /* dns_opcode */
+
+
+enum dns_rcode {
+ DNS_RC_NOERROR = 0,
+ DNS_RC_FORMERR = 1,
+ DNS_RC_SERVFAIL = 2,
+ DNS_RC_NXDOMAIN = 3,
+ DNS_RC_NOTIMP = 4,
+ DNS_RC_REFUSED = 5,
+ DNS_RC_YXDOMAIN = 6,
+ DNS_RC_YXRRSET = 7,
+ DNS_RC_NXRRSET = 8,
+ DNS_RC_NOTAUTH = 9,
+ DNS_RC_NOTZONE = 10,
+
+ /* EDNS(0) extended RCODEs */
+ DNS_RC_BADVERS = 16,
+}; /* dns_rcode */
+
+
+/*
+ * NOTE: These string functions need a small buffer in case the literal
+ * integer value needs to be printed and returned. UNLESS this buffer is
+ * SPECIFIED, the returned string has ONLY BLOCK SCOPE.
+ */
+#define DNS_STRMAXLEN 47 /* "QUESTION|ANSWER|AUTHORITY|ADDITIONAL" */
+
+DNS_PUBLIC const char *dns_strsection(enum dns_section, char *);
+
+DNS_PUBLIC enum dns_section dns_isection(const char *);
+
+DNS_PUBLIC const char *dns_strclass(enum dns_class, char *);
+
+DNS_PUBLIC enum dns_class dns_iclass(const char *);
+
+DNS_PUBLIC const char *dns_strtype(enum dns_type, char *);
+
+DNS_PUBLIC enum dns_type dns_itype(const char *);
+
+DNS_PUBLIC const char *dns_stropcode(enum dns_opcode);
+
+DNS_PUBLIC enum dns_opcode dns_iopcode(const char *);
+
+DNS_PUBLIC const char *dns_strrcode(enum dns_rcode);
+
+DNS_PUBLIC enum dns_rcode dns_ircode(const char *);
+
+
+/*
+ * A T O M I C I N T E R F A C E S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+typedef unsigned long dns_atomic_t;
+
+typedef unsigned long dns_refcount_t; /* must be same value type as dns_atomic_t */
+
+
+/*
+ * C R Y P T O I N T E R F A C E S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+typedef unsigned dns_random_f(void);
+
+DNS_PUBLIC dns_random_f **dns_random_p(void);
+
+#define dns_random (*dns_random_p()) /* was extern unsigned (*dns_random)(void) before 20160523 API */
+
+
+/*
+ * P A C K E T I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_header {
+ unsigned qid:16;
+
+#if (defined BYTE_ORDER && BYTE_ORDER == BIG_ENDIAN) || (defined __sun && defined _BIG_ENDIAN)
+ unsigned qr:1;
+ unsigned opcode:4;
+ unsigned aa:1;
+ unsigned tc:1;
+ unsigned rd:1;
+
+ unsigned ra:1;
+ unsigned unused:3;
+ unsigned rcode:4;
+#else
+ unsigned rd:1;
+ unsigned tc:1;
+ unsigned aa:1;
+ unsigned opcode:4;
+ unsigned qr:1;
+
+ unsigned rcode:4;
+ unsigned unused:3;
+ unsigned ra:1;
+#endif
+
+ unsigned qdcount:16;
+ unsigned ancount:16;
+ unsigned nscount:16;
+ unsigned arcount:16;
+}; /* struct dns_header */
+
+#define dns_header(p) (&(p)->header)
+
+
+#ifndef DNS_P_QBUFSIZ
+#define DNS_P_QBUFSIZ dns_p_calcsize(256 + 4)
+#endif
+
+#ifndef DNS_P_DICTSIZE
+#define DNS_P_DICTSIZE 16
+#endif
+
+struct dns_packet {
+ unsigned short dict[DNS_P_DICTSIZE];
+
+ struct dns_p_memo {
+ struct dns_s_memo {
+ unsigned short base, end;
+ } qd, an, ns, ar;
+
+ struct {
+ unsigned short p;
+ unsigned short maxudp;
+ unsigned ttl;
+ } opt;
+ } memo;
+
+ struct { struct dns_packet *cqe_next, *cqe_prev; } cqe;
+
+ size_t size, end;
+
+ int:16; /* tcp padding */
+
+ DNS_PRAGMA_EXTENSION union {
+ struct dns_header header;
+ unsigned char data[1];
+ };
+}; /* struct dns_packet */
+
+#define dns_p_calcsize(n) (offsetof(struct dns_packet, data) + DNS_PP_MAX(12, (n)))
+
+#define dns_p_sizeof(P) dns_p_calcsize((P)->end)
+
+/** takes size of entire packet structure as allocated */
+DNS_PUBLIC struct dns_packet *dns_p_init(struct dns_packet *, size_t);
+
+/** takes size of maximum desired payload */
+DNS_PUBLIC struct dns_packet *dns_p_make(size_t, int *);
+
+DNS_PUBLIC int dns_p_grow(struct dns_packet **);
+
+DNS_PUBLIC struct dns_packet *dns_p_copy(struct dns_packet *, const struct dns_packet *);
+
+#define dns_p_opcode(P) (dns_header(P)->opcode)
+
+DNS_PUBLIC enum dns_rcode dns_p_rcode(struct dns_packet *);
+
+DNS_PUBLIC unsigned dns_p_count(struct dns_packet *, enum dns_section);
+
+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 *);
+
+DNS_PUBLIC void dns_p_dictadd(struct dns_packet *, unsigned short);
+
+DNS_PUBLIC struct dns_packet *dns_p_merge(struct dns_packet *, enum dns_section, struct dns_packet *, enum dns_section, int *);
+
+DNS_PUBLIC void dns_p_dump(struct dns_packet *, FILE *);
+
+DNS_PUBLIC int dns_p_study(struct dns_packet *);
+
+
+/*
+ * D O M A I N N A M E I N T E R F A C E S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define DNS_D_MAXLABEL 63 /* + 1 '\0' */
+#define DNS_D_MAXNAME 255 /* + 1 '\0' */
+
+#define DNS_D_ANCHOR 1 /* anchor domain w/ root "." */
+#define DNS_D_CLEAVE 2 /* cleave sub-domain */
+#define DNS_D_TRIM 4 /* remove superfluous dots */
+
+DNS_PUBLIC char *dns_d_init(void *, size_t, const void *, size_t, int);
+
+DNS_PUBLIC size_t dns_d_anchor(void *, size_t, const void *, size_t);
+
+DNS_PUBLIC size_t dns_d_cleave(void *, size_t, const void *, size_t);
+
+DNS_PUBLIC size_t dns_d_comp(void *, size_t, const void *, size_t, struct dns_packet *, int *);
+
+DNS_PUBLIC size_t dns_d_expand(void *, size_t, unsigned short, struct dns_packet *, int *);
+
+DNS_PUBLIC unsigned short dns_d_skip(unsigned short, struct dns_packet *);
+
+DNS_PUBLIC int dns_d_push(struct dns_packet *, const void *, size_t);
+
+DNS_PUBLIC size_t dns_d_cname(void *, size_t, const void *, size_t, struct dns_packet *, int *error);
+
+
+/*
+ * R E S O U R C E R E C O R D I N T E R F A C E S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_rr {
+ enum dns_section section;
+
+ struct {
+ unsigned short p;
+ unsigned short len;
+ } dn;
+
+ enum dns_type type;
+ enum dns_class class;
+ unsigned ttl;
+
+ struct {
+ unsigned short p;
+ unsigned short len;
+ } rd;
+}; /* struct dns_rr */
+
+
+DNS_PUBLIC int dns_rr_copy(struct dns_packet *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_rr_parse(struct dns_rr *, unsigned short, struct dns_packet *);
+
+DNS_PUBLIC unsigned short dns_rr_skip(unsigned short, struct dns_packet *);
+
+DNS_PUBLIC int dns_rr_cmp(struct dns_rr *, struct dns_packet *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC size_t dns_rr_print(void *, size_t, struct dns_rr *, struct dns_packet *, int *);
+
+
+struct dns_rr_i {
+ enum dns_section section;
+ const void *name;
+ enum dns_type type;
+ enum dns_class class;
+ const void *data;
+
+ int follow;
+
+ int (*sort)(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
+ unsigned args[2];
+
+ struct {
+ unsigned short next;
+ unsigned short count;
+
+ unsigned exec;
+ unsigned regs[2];
+ } state, saved;
+}; /* struct dns_rr_i */
+
+DNS_PUBLIC int dns_rr_i_packet(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
+
+DNS_PUBLIC int dns_rr_i_order(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
+
+DNS_PUBLIC int dns_rr_i_shuffle(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
+
+DNS_PUBLIC void dns_rr_i_init(struct dns_rr_i *);
+
+#define dns_rr_i_save(i) ((i)->saved = (i)->state)
+#define dns_rr_i_rewind(i) ((i)->state = (i)->saved)
+#define dns_rr_i_count(i) ((i)->state.count)
+
+DNS_PUBLIC unsigned dns_rr_grep(struct dns_rr *, unsigned, struct dns_rr_i *, struct dns_packet *, int *);
+
+#define dns_rr_foreach_(rr, P, ...) \
+ for (struct dns_rr_i DNS_PP_XPASTE(i, __LINE__) = { __VA_ARGS__ }; dns_rr_grep((rr), 1, &DNS_PP_XPASTE(i, __LINE__), (P), NULL); )
+
+#define dns_rr_foreach(...) dns_rr_foreach_(__VA_ARGS__)
+
+
+/*
+ * A R E S O U R C E R E C O R D
+ */
+
+struct dns_a {
+ struct in_addr addr;
+}; /* struct dns_a */
+
+DNS_PUBLIC int dns_a_parse(struct dns_a *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_a_push(struct dns_packet *, struct dns_a *);
+
+DNS_PUBLIC int dns_a_cmp(const struct dns_a *, const struct dns_a *);
+
+DNS_PUBLIC size_t dns_a_print(void *, size_t, struct dns_a *);
+
+DNS_PUBLIC size_t dns_a_arpa(void *, size_t, const struct dns_a *);
+
+
+/*
+ * AAAA R E S O U R C E R E C O R D
+ */
+
+struct dns_aaaa {
+ struct in6_addr addr;
+}; /* struct dns_aaaa */
+
+DNS_PUBLIC int dns_aaaa_parse(struct dns_aaaa *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_aaaa_push(struct dns_packet *, struct dns_aaaa *);
+
+DNS_PUBLIC int dns_aaaa_cmp(const struct dns_aaaa *, const struct dns_aaaa *);
+
+DNS_PUBLIC size_t dns_aaaa_print(void *, size_t, struct dns_aaaa *);
+
+DNS_PUBLIC size_t dns_aaaa_arpa(void *, size_t, const struct dns_aaaa *);
+
+
+/*
+ * MX R E S O U R C E R E C O R D
+ */
+
+struct dns_mx {
+ unsigned short preference;
+ char host[DNS_D_MAXNAME + 1];
+}; /* struct dns_mx */
+
+DNS_PUBLIC int dns_mx_parse(struct dns_mx *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_mx_push(struct dns_packet *, struct dns_mx *);
+
+DNS_PUBLIC int dns_mx_cmp(const struct dns_mx *, const struct dns_mx *);
+
+DNS_PUBLIC size_t dns_mx_print(void *, size_t, struct dns_mx *);
+
+DNS_PUBLIC size_t dns_mx_cname(void *, size_t, struct dns_mx *);
+
+
+/*
+ * NS R E S O U R C E R E C O R D
+ */
+
+struct dns_ns {
+ char host[DNS_D_MAXNAME + 1];
+}; /* struct dns_ns */
+
+DNS_PUBLIC int dns_ns_parse(struct dns_ns *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_ns_push(struct dns_packet *, struct dns_ns *);
+
+DNS_PUBLIC int dns_ns_cmp(const struct dns_ns *, const struct dns_ns *);
+
+DNS_PUBLIC size_t dns_ns_print(void *, size_t, struct dns_ns *);
+
+DNS_PUBLIC size_t dns_ns_cname(void *, size_t, struct dns_ns *);
+
+
+/*
+ * CNAME R E S O U R C E R E C O R D
+ */
+
+struct dns_cname {
+ char host[DNS_D_MAXNAME + 1];
+}; /* struct dns_cname */
+
+DNS_PUBLIC int dns_cname_parse(struct dns_cname *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_cname_push(struct dns_packet *, struct dns_cname *);
+
+DNS_PUBLIC int dns_cname_cmp(const struct dns_cname *, const struct dns_cname *);
+
+DNS_PUBLIC size_t dns_cname_print(void *, size_t, struct dns_cname *);
+
+DNS_PUBLIC size_t dns_cname_cname(void *, size_t, struct dns_cname *);
+
+
+/*
+ * SOA R E S O U R C E R E C O R D
+ */
+
+struct dns_soa {
+ char mname[DNS_D_MAXNAME + 1];
+ char rname[DNS_D_MAXNAME + 1];
+ unsigned serial, refresh, retry, expire, minimum;
+}; /* struct dns_soa */
+
+DNS_PUBLIC int dns_soa_parse(struct dns_soa *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_soa_push(struct dns_packet *, struct dns_soa *);
+
+DNS_PUBLIC int dns_soa_cmp(const struct dns_soa *, const struct dns_soa *);
+
+DNS_PUBLIC size_t dns_soa_print(void *, size_t, struct dns_soa *);
+
+
+/*
+ * PTR R E S O U R C E R E C O R D
+ */
+
+struct dns_ptr {
+ char host[DNS_D_MAXNAME + 1];
+}; /* struct dns_ptr */
+
+DNS_PUBLIC int dns_ptr_parse(struct dns_ptr *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_ptr_push(struct dns_packet *, struct dns_ptr *);
+
+DNS_PUBLIC int dns_ptr_cmp(const struct dns_ptr *, const struct dns_ptr *);
+
+DNS_PUBLIC size_t dns_ptr_print(void *, size_t, struct dns_ptr *);
+
+DNS_PUBLIC size_t dns_ptr_cname(void *, size_t, struct dns_ptr *);
+
+DNS_PUBLIC size_t dns_ptr_qname(void *, size_t, int, void *);
+
+
+/*
+ * SRV R E S O U R C E R E C O R D
+ */
+
+struct dns_srv {
+ unsigned short priority;
+ unsigned short weight;
+ unsigned short port;
+ char target[DNS_D_MAXNAME + 1];
+}; /* struct dns_srv */
+
+DNS_PUBLIC int dns_srv_parse(struct dns_srv *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_srv_push(struct dns_packet *, struct dns_srv *);
+
+DNS_PUBLIC int dns_srv_cmp(const struct dns_srv *, const struct dns_srv *);
+
+DNS_PUBLIC size_t dns_srv_print(void *, size_t, struct dns_srv *);
+
+DNS_PUBLIC size_t dns_srv_cname(void *, size_t, struct dns_srv *);
+
+
+/*
+ * OPT R E S O U R C E R E C O R D
+ */
+
+#ifndef DNS_OPT_MINDATA
+#define DNS_OPT_MINDATA 256
+#endif
+
+#define DNS_OPT_DNSSEC 0x8000
+
+struct dns_opt {
+ enum dns_rcode rcode;
+ unsigned char version;
+ unsigned short flags;
+
+ union {
+ unsigned short maxsize; /* deprecated as confusing */
+ unsigned short maxudp; /* maximum UDP payload size */
+ };
+
+ size_t size, len;
+ unsigned char data[DNS_OPT_MINDATA];
+}; /* struct dns_opt */
+
+#define DNS_OPT_INIT(opt) { .size = sizeof (*opt) - offsetof(struct dns_opt, data) }
+
+DNS_PUBLIC struct dns_opt *dns_opt_init(struct dns_opt *, size_t);
+
+DNS_PUBLIC int dns_opt_parse(struct dns_opt *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_opt_push(struct dns_packet *, struct dns_opt *);
+
+DNS_PUBLIC int dns_opt_cmp(const struct dns_opt *, const struct dns_opt *);
+
+DNS_PUBLIC size_t dns_opt_print(void *, size_t, struct dns_opt *);
+
+DNS_PUBLIC unsigned int dns_opt_ttl(const struct dns_opt *);
+
+DNS_PUBLIC unsigned short dns_opt_class(const struct dns_opt *);
+
+DNS_PUBLIC dns_error_t dns_opt_data_push(struct dns_opt *, unsigned char, unsigned short, const void *);
+
+
+/*
+ * SSHFP R E S O U R C E R E C O R D
+ */
+
+struct dns_sshfp {
+ enum dns_sshfp_key {
+ DNS_SSHFP_RSA = 1,
+ DNS_SSHFP_DSA = 2,
+ } algo;
+
+ enum dns_sshfp_digest {
+ DNS_SSHFP_SHA1 = 1,
+ } type;
+
+ union {
+ unsigned char sha1[20];
+ } digest;
+}; /* struct dns_sshfp */
+
+DNS_PUBLIC int dns_sshfp_parse(struct dns_sshfp *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_sshfp_push(struct dns_packet *, struct dns_sshfp *);
+
+DNS_PUBLIC int dns_sshfp_cmp(const struct dns_sshfp *, const struct dns_sshfp *);
+
+DNS_PUBLIC size_t dns_sshfp_print(void *, size_t, struct dns_sshfp *);
+
+
+/*
+ * TXT R E S O U R C E R E C O R D
+ */
+
+#ifndef DNS_TXT_MINDATA
+#define DNS_TXT_MINDATA 1024
+#endif
+
+struct dns_txt {
+ size_t size, len;
+ unsigned char data[DNS_TXT_MINDATA];
+}; /* struct dns_txt */
+
+DNS_PUBLIC struct dns_txt *dns_txt_init(struct dns_txt *, size_t);
+
+DNS_PUBLIC int dns_txt_parse(struct dns_txt *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_txt_push(struct dns_packet *, struct dns_txt *);
+
+DNS_PUBLIC int dns_txt_cmp(const struct dns_txt *, const struct dns_txt *);
+
+DNS_PUBLIC size_t dns_txt_print(void *, size_t, struct dns_txt *);
+
+
+/*
+ * ANY R E S O U R C E R E C O R D
+ */
+
+union dns_any {
+ struct dns_a a;
+ struct dns_aaaa aaaa;
+ struct dns_mx mx;
+ struct dns_ns ns;
+ struct dns_cname cname;
+ struct dns_soa soa;
+ struct dns_ptr ptr;
+ struct dns_srv srv;
+ struct dns_opt opt;
+ struct dns_sshfp sshfp;
+ struct dns_txt txt, spf, rdata;
+}; /* union dns_any */
+
+#define DNS_ANY_INIT(any) { .rdata = { .size = sizeof *(any) - offsetof(struct dns_txt, data) } }
+
+DNS_PUBLIC union dns_any *dns_any_init(union dns_any *, size_t);
+
+DNS_PUBLIC int dns_any_parse(union dns_any *, struct dns_rr *, struct dns_packet *);
+
+DNS_PUBLIC int dns_any_push(struct dns_packet *, union dns_any *, enum dns_type);
+
+DNS_PUBLIC int dns_any_cmp(const union dns_any *, enum dns_type, const union dns_any *, enum dns_type);
+
+DNS_PUBLIC size_t dns_any_print(void *, size_t, union dns_any *, enum dns_type);
+
+DNS_PUBLIC size_t dns_any_cname(void *, size_t, union dns_any *, enum dns_type);
+
+
+/*
+ * H O S T S I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_hosts;
+
+DNS_PUBLIC struct dns_hosts *dns_hosts_open(int *);
+
+DNS_PUBLIC void dns_hosts_close(struct dns_hosts *);
+
+DNS_PUBLIC dns_refcount_t dns_hosts_acquire(struct dns_hosts *);
+
+DNS_PUBLIC dns_refcount_t dns_hosts_release(struct dns_hosts *);
+
+DNS_PUBLIC struct dns_hosts *dns_hosts_mortal(struct dns_hosts *);
+
+DNS_PUBLIC struct dns_hosts *dns_hosts_local(int *);
+
+DNS_PUBLIC int dns_hosts_loadfile(struct dns_hosts *, FILE *);
+
+DNS_PUBLIC int dns_hosts_loadpath(struct dns_hosts *, const char *);
+
+DNS_PUBLIC int dns_hosts_dump(struct dns_hosts *, FILE *);
+
+DNS_PUBLIC int dns_hosts_insert(struct dns_hosts *, int, const void *, const void *, _Bool);
+
+DNS_PUBLIC struct dns_packet *dns_hosts_query(struct dns_hosts *, struct dns_packet *, int *);
+
+
+/*
+ * R E S O L V . C O N F I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_resolv_conf {
+ struct sockaddr_storage nameserver[3];
+
+ char search[4][DNS_D_MAXNAME + 1];
+
+ /* (f)ile, (b)ind, (c)ache */
+ char lookup[4 * (1 + (4 * 2))];
+
+ /* getaddrinfo family by preference order ("inet4", "inet6") */
+ int family[3];
+
+ struct {
+ _Bool edns0;
+
+ unsigned ndots;
+
+ unsigned timeout;
+
+ unsigned attempts;
+
+ _Bool rotate;
+
+ _Bool recurse;
+
+ _Bool smart;
+
+ enum {
+ DNS_RESCONF_TCP_ENABLE,
+ DNS_RESCONF_TCP_ONLY,
+ DNS_RESCONF_TCP_SOCKS,
+ DNS_RESCONF_TCP_DISABLE,
+ } tcp;
+ } options;
+
+ struct sockaddr_storage iface;
+
+ struct { /* PRIVATE */
+ dns_atomic_t refcount;
+ } _;
+}; /* struct dns_resolv_conf */
+
+DNS_PUBLIC struct dns_resolv_conf *dns_resconf_open(int *);
+
+DNS_PUBLIC void dns_resconf_close(struct dns_resolv_conf *);
+
+DNS_PUBLIC dns_refcount_t dns_resconf_acquire(struct dns_resolv_conf *);
+
+DNS_PUBLIC dns_refcount_t dns_resconf_release(struct dns_resolv_conf *);
+
+DNS_PUBLIC struct dns_resolv_conf *dns_resconf_mortal(struct dns_resolv_conf *);
+
+DNS_PUBLIC struct dns_resolv_conf *dns_resconf_local(int *);
+
+DNS_PUBLIC struct dns_resolv_conf *dns_resconf_root(int *);
+
+DNS_PUBLIC int dns_resconf_pton(struct sockaddr_storage *, const char *);
+
+DNS_PUBLIC int dns_resconf_loadfile(struct dns_resolv_conf *, FILE *);
+
+DNS_PUBLIC int dns_resconf_loadpath(struct dns_resolv_conf *, const char *);
+
+DNS_PUBLIC int dns_nssconf_loadfile(struct dns_resolv_conf *, FILE *);
+
+DNS_PUBLIC int dns_nssconf_loadpath(struct dns_resolv_conf *, const char *);
+
+DNS_PUBLIC int dns_resconf_dump(struct dns_resolv_conf *, FILE *);
+
+DNS_PUBLIC int dns_nssconf_dump(struct dns_resolv_conf *, FILE *);
+
+DNS_PUBLIC int dns_resconf_setiface(struct dns_resolv_conf *, const char *, unsigned short);
+
+typedef unsigned long dns_resconf_i_t;
+
+DNS_PUBLIC size_t dns_resconf_search(void *, size_t, const void *, size_t, struct dns_resolv_conf *, dns_resconf_i_t *);
+
+
+/*
+ * H I N T S E R V E R I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_hints;
+
+DNS_PUBLIC struct dns_hints *dns_hints_open(struct dns_resolv_conf *, int *);
+
+DNS_PUBLIC void dns_hints_close(struct dns_hints *);
+
+DNS_PUBLIC dns_refcount_t dns_hints_acquire(struct dns_hints *);
+
+DNS_PUBLIC dns_refcount_t dns_hints_release(struct dns_hints *);
+
+DNS_PUBLIC struct dns_hints *dns_hints_mortal(struct dns_hints *);
+
+DNS_PUBLIC int dns_hints_insert(struct dns_hints *, const char *, const struct sockaddr *, unsigned);
+
+DNS_PUBLIC unsigned dns_hints_insert_resconf(struct dns_hints *, const char *, const struct dns_resolv_conf *, int *);
+
+DNS_PUBLIC struct dns_hints *dns_hints_local(struct dns_resolv_conf *, int *);
+
+DNS_PUBLIC struct dns_hints *dns_hints_root(struct dns_resolv_conf *, int *);
+
+DNS_PUBLIC struct dns_packet *dns_hints_query(struct dns_hints *, struct dns_packet *, int *);
+
+DNS_PUBLIC int dns_hints_dump(struct dns_hints *, FILE *);
+
+
+struct dns_hints_i {
+ const char *zone;
+
+ struct {
+ unsigned next;
+ unsigned seed;
+ } state;
+}; /* struct dns_hints_i */
+
+
+DNS_PUBLIC unsigned dns_hints_grep(struct sockaddr **, socklen_t *, unsigned, struct dns_hints_i *, struct dns_hints *);
+
+
+/*
+ * C A C H E I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_cache {
+ void *state;
+
+ dns_refcount_t (*acquire)(struct dns_cache *);
+ dns_refcount_t (*release)(struct dns_cache *);
+
+ struct dns_packet *(*query)(struct dns_packet *, struct dns_cache *, int *);
+
+ int (*submit)(struct dns_packet *, struct dns_cache *);
+ int (*check)(struct dns_cache *);
+ struct dns_packet *(*fetch)(struct dns_cache *, int *);
+
+ int (*pollfd)(struct dns_cache *);
+ short (*events)(struct dns_cache *);
+ void (*clear)(struct dns_cache *);
+
+ union {
+ long i;
+ void *p;
+ } arg[3];
+
+ struct { /* PRIVATE */
+ dns_atomic_t refcount;
+ } _;
+}; /* struct dns_cache */
+
+
+DNS_PUBLIC struct dns_cache *dns_cache_init(struct dns_cache *);
+
+DNS_PUBLIC void dns_cache_close(struct dns_cache *);
+
+
+/*
+ * A P P L I C A T I O N I N T E R F A C E
+ *
+ * Options to change the behavior of the API. Applies across all the
+ * different components.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define DNS_OPTS_INITIALIZER_ { 0, 0 }, 0, 0
+#define DNS_OPTS_INITIALIZER { DNS_OPTS_INITIALIZER_ }
+
+struct dns_options {
+ /*
+ * If the callback closes *fd, it must set it to -1. Otherwise, the
+ * descriptor is queued and lazily closed at object destruction or
+ * by an explicit call to _clear(). This allows safe use of
+ * kqueue(2), epoll(2), et al -style persistent events.
+ */
+ struct {
+ void *arg;
+ int (*cb)(int *fd, void *arg);
+ } closefd;
+
+ /* bitmask for _events() routines */
+ enum dns_events {
+ DNS_SYSPOLL,
+ DNS_LIBEVENT,
+ } events;
+
+ /* Use this SOCKS server. */
+ const struct sockaddr_storage *socks_host;
+
+ /* Credentials for the SOCKS server (optional). */
+ const char *socks_user;
+ const char *socks_password;
+}; /* struct dns_options */
+
+
+/*
+ * S T A T S I N T E R F A C E S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_stat {
+ size_t queries;
+
+ struct {
+ struct {
+ size_t count, bytes;
+ } sent, rcvd;
+ } udp, tcp;
+}; /* struct dns_stat */
+
+
+/*
+ * S O C K E T I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_socket;
+
+DNS_PUBLIC struct dns_socket *dns_so_open(const struct sockaddr *, int, const struct dns_options *, int *error);
+
+DNS_PUBLIC void dns_so_close(struct dns_socket *);
+
+DNS_PUBLIC void dns_so_reset(struct dns_socket *);
+
+DNS_PUBLIC unsigned short dns_so_mkqid(struct dns_socket *so);
+
+DNS_PUBLIC struct dns_packet *dns_so_query(struct dns_socket *, struct dns_packet *, struct sockaddr *, int *);
+
+DNS_PUBLIC int dns_so_submit(struct dns_socket *, struct dns_packet *, struct sockaddr *);
+
+DNS_PUBLIC int dns_so_check(struct dns_socket *);
+
+DNS_PUBLIC struct dns_packet *dns_so_fetch(struct dns_socket *, int *);
+
+DNS_PUBLIC time_t dns_so_elapsed(struct dns_socket *);
+
+DNS_PUBLIC void dns_so_clear(struct dns_socket *);
+
+DNS_PUBLIC int dns_so_events(struct dns_socket *);
+
+DNS_PUBLIC int dns_so_pollfd(struct dns_socket *);
+
+DNS_PUBLIC int dns_so_poll(struct dns_socket *, int);
+
+DNS_PUBLIC const struct dns_stat *dns_so_stat(struct dns_socket *);
+
+DNS_PUBLIC struct dns_trace *dns_so_trace(struct dns_socket *);
+
+DNS_PUBLIC void dns_so_settrace(struct dns_socket *, struct dns_trace *);
+
+
+/*
+ * R E S O L V E R I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_resolver;
+
+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 *);
+
+DNS_PUBLIC struct dns_resolver *dns_res_stub(const struct dns_options *, int *);
+
+DNS_PUBLIC void dns_res_reset(struct dns_resolver *);
+
+DNS_PUBLIC void dns_res_close(struct dns_resolver *);
+
+DNS_PUBLIC dns_refcount_t dns_res_acquire(struct dns_resolver *);
+
+DNS_PUBLIC dns_refcount_t dns_res_release(struct dns_resolver *);
+
+DNS_PUBLIC struct dns_resolver *dns_res_mortal(struct dns_resolver *);
+
+DNS_PUBLIC int dns_res_submit(struct dns_resolver *, const char *, enum dns_type, enum dns_class);
+
+DNS_PUBLIC int dns_res_submit2(struct dns_resolver *, const char *, size_t, enum dns_type, enum dns_class);
+
+DNS_PUBLIC int dns_res_check(struct dns_resolver *);
+
+DNS_PUBLIC struct dns_packet *dns_res_fetch(struct dns_resolver *, int *);
+
+DNS_PUBLIC time_t dns_res_elapsed(struct dns_resolver *);
+
+DNS_PUBLIC void dns_res_clear(struct dns_resolver *);
+
+DNS_PUBLIC int dns_res_events(struct dns_resolver *);
+
+DNS_PUBLIC int dns_res_pollfd(struct dns_resolver *);
+
+DNS_PUBLIC time_t dns_res_timeout(struct dns_resolver *);
+
+DNS_PUBLIC int dns_res_poll(struct dns_resolver *, int);
+
+DNS_PUBLIC struct dns_packet *dns_res_query(struct dns_resolver *, const char *, enum dns_type, enum dns_class, int, int *);
+
+DNS_PUBLIC const struct dns_stat *dns_res_stat(struct dns_resolver *);
+
+DNS_PUBLIC void dns_res_sethints(struct dns_resolver *, struct dns_hints *);
+
+DNS_PUBLIC struct dns_trace *dns_res_trace(struct dns_resolver *);
+
+DNS_PUBLIC void dns_res_settrace(struct dns_resolver *, struct dns_trace *);
+
+
+/*
+ * A D D R I N F O I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+struct dns_addrinfo;
+
+DNS_PUBLIC struct dns_addrinfo *dns_ai_open(const char *, const char *, enum dns_type, const struct addrinfo *, struct dns_resolver *, int *);
+
+DNS_PUBLIC void dns_ai_close(struct dns_addrinfo *);
+
+DNS_PUBLIC int dns_ai_nextent(struct addrinfo **, struct dns_addrinfo *);
+
+DNS_PUBLIC size_t dns_ai_print(void *, size_t, struct addrinfo *, struct dns_addrinfo *);
+
+DNS_PUBLIC time_t dns_ai_elapsed(struct dns_addrinfo *);
+
+DNS_PUBLIC void dns_ai_clear(struct dns_addrinfo *);
+
+DNS_PUBLIC int dns_ai_events(struct dns_addrinfo *);
+
+DNS_PUBLIC int dns_ai_pollfd(struct dns_addrinfo *);
+
+DNS_PUBLIC time_t dns_ai_timeout(struct dns_addrinfo *);
+
+DNS_PUBLIC int dns_ai_poll(struct dns_addrinfo *, int);
+
+DNS_PUBLIC const struct dns_stat *dns_ai_stat(struct dns_addrinfo *);
+
+DNS_PUBLIC struct dns_trace *dns_ai_trace(struct dns_addrinfo *);
+
+DNS_PUBLIC void dns_ai_settrace(struct dns_addrinfo *, struct dns_trace *);
+
+
+/*
+ * Q U E R Y T R A C I N G I N T E R F A C E
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define DNS_TRACE_ID_C(n) UINT64_C(n)
+typedef uint64_t dns_trace_id_t;
+
+#define DNS_TRACE_ABI 0x20160803
+
+struct dns_trace_event {
+ enum {
+ DNS_TE_RES_SUBMIT = 1,
+ DNS_TE_RES_FETCH = 99,
+
+ DNS_TE_SO_SUBMIT = 100,
+ DNS_TE_SO_VERIFY,
+ DNS_TE_SO_FETCH = 199,
+
+ DNS_TE_SYS_CONNECT = 200,
+ DNS_TE_SYS_SEND,
+ DNS_TE_SYS_RECV,
+ } type;
+
+ size_t size;
+ dns_trace_id_t id;
+ struct timespec ts;
+ int abi;
+
+ union {
+ struct {
+ char qname[DNS_D_MAXNAME + 1];
+ enum dns_type qtype;
+ enum dns_class qclass;
+ int error;
+ } res_submit;
+
+ struct {
+ int error;
+ } res_fetch;
+
+ struct {
+ struct sockaddr_storage haddr;
+ char hname[DNS_D_MAXNAME + 1];
+ int error;
+ } so_submit;
+
+ struct {
+ int error;
+ } so_verify;
+
+ struct {
+ int error;
+ } so_fetch;
+
+ struct {
+ struct sockaddr_storage src, dst;
+ int socktype;
+ dns_error_t error;
+ } sys_connect, sys_send, sys_recv;
+ };
+
+ unsigned char data[];
+};
+
+static inline size_t dns_te_datasize(const struct dns_trace_event *te) {
+ size_t n = offsetof(struct dns_trace_event, data);
+ return (n <= te->size)? te->size - n : 0;
+}
+
+struct dns_trace;
+
+DNS_PUBLIC int dns_trace_abi(void);
+
+DNS_PUBLIC struct dns_trace *dns_trace_open(FILE *, dns_error_t *);
+
+DNS_PUBLIC void dns_trace_close(struct dns_trace *);
+
+DNS_PUBLIC dns_refcount_t dns_trace_acquire(struct dns_trace *);
+
+DNS_PUBLIC dns_refcount_t dns_trace_release(struct dns_trace *);
+
+DNS_PUBLIC dns_trace_id_t dns_trace_id(struct dns_trace *);
+
+DNS_PUBLIC dns_trace_id_t dns_trace_setid(struct dns_trace *, dns_trace_id_t);
+
+DNS_PUBLIC struct dns_trace_event *dns_trace_get(struct dns_trace *, struct dns_trace_event **, dns_error_t *);
+
+DNS_PUBLIC struct dns_trace_event *dns_trace_tag(struct dns_trace *, struct dns_trace_event *);
+
+DNS_PUBLIC dns_error_t dns_trace_put(struct dns_trace *, const struct dns_trace_event *, const void *, size_t);
+
+DNS_PUBLIC dns_error_t dns_trace_dump(struct dns_trace *, FILE *);
+
+DNS_PUBLIC struct dns_trace_event *dns_trace_fget(struct dns_trace_event **, FILE *, dns_error_t *);
+
+DNS_PUBLIC dns_error_t dns_trace_fput(const struct dns_trace_event *, const void *, size_t, FILE *);
+
+
+/*
+ * U T I L I T Y I N T E R F A C E S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+DNS_PUBLIC size_t dns_strlcpy(char *, const char *, size_t);
+
+DNS_PUBLIC size_t dns_strlcat(char *, const char *, size_t);
+
+
+/*
+ * M A C R O M A G I C S
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define DNS_PP_MIN(a, b) (((a) < (b))? (a) : (b))
+#define DNS_PP_MAX(a, b) (((a) > (b))? (a) : (b))
+#define DNS_PP_NARG_(a, b, c, d, e, f, g, h, i, j, k, N,...) N
+#define DNS_PP_NARG(...) DNS_PP_NARG_(__VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+#define DNS_PP_CALL(F, ...) F(__VA_ARGS__)
+#define DNS_PP_PASTE(x, y) x##y
+#define DNS_PP_XPASTE(x, y) DNS_PP_PASTE(x, y)
+#define DNS_PP_STRINGIFY_(s) #s
+#define DNS_PP_STRINGIFY(s) DNS_PP_STRINGIFY_(s)
+#define DNS_PP_D1 0
+#define DNS_PP_D2 1
+#define DNS_PP_D3 2
+#define DNS_PP_D4 3
+#define DNS_PP_D5 4
+#define DNS_PP_D6 5
+#define DNS_PP_D7 6
+#define DNS_PP_D8 7
+#define DNS_PP_D9 8
+#define DNS_PP_D10 9
+#define DNS_PP_D11 10
+#define DNS_PP_DEC(N) DNS_PP_XPASTE(DNS_PP_D, N)
+
+#endif /* DNS_H */