summaryrefslogtreecommitdiffstats
path: root/contrib/librdns/dns_private.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--contrib/librdns/dns_private.h338
1 files changed, 338 insertions, 0 deletions
diff --git a/contrib/librdns/dns_private.h b/contrib/librdns/dns_private.h
new file mode 100644
index 0000000..c240deb
--- /dev/null
+++ b/contrib/librdns/dns_private.h
@@ -0,0 +1,338 @@
+/* Copyright (c) 2014, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DNS_PRIVATE_H_
+#define DNS_PRIVATE_H_
+
+#include "config.h"
+#include "uthash.h"
+#include "utlist.h"
+#include "khash.h"
+#include "rdns.h"
+#include "upstream.h"
+#include "ref.h"
+
+static const int dns_port = 53;
+static const int default_io_cnt = 8;
+static const int default_tcp_io_cnt = 1;
+
+#define UDP_PACKET_SIZE (4096)
+
+#define DNS_COMPRESSION_BITS 0xC0
+
+#define DNS_D_MAXLABEL 63 /* + 1 '\0' */
+#define DNS_D_MAXNAME 255 /* + 1 '\0' */
+
+#define RESOLV_CONF "/etc/resolv.conf"
+
+struct dns_header {
+ unsigned int qid :16;
+
+#if BYTE_ORDER == BIG_ENDIAN
+ unsigned int qr:1;
+ unsigned int opcode:4;
+ unsigned int aa:1;
+ unsigned int tc:1;
+ unsigned int rd:1;
+
+ unsigned int ra:1;
+ unsigned int cd : 1;
+ unsigned int ad : 1;
+ unsigned int z : 1;
+ unsigned int rcode:4;
+#else
+ unsigned int rd :1;
+ unsigned int tc :1;
+ unsigned int aa :1;
+ unsigned int opcode :4;
+ unsigned int qr :1;
+
+ unsigned int rcode :4;
+ unsigned int z : 1;
+ unsigned int ad : 1;
+ unsigned int cd : 1;
+ unsigned int ra :1;
+#endif
+
+ unsigned int qdcount :16;
+ unsigned int ancount :16;
+ unsigned int nscount :16;
+ unsigned int arcount :16;
+};
+
+/**
+ * Represents DNS server
+ */
+struct rdns_server {
+ char *name;
+ unsigned int port;
+ unsigned int io_cnt;
+ unsigned int tcp_io_cnt;
+
+ struct rdns_io_channel **io_channels;
+ struct rdns_io_channel **tcp_io_channels;
+ void *ups_elt;
+ upstream_entry_t up;
+};
+
+enum rdns_request_state {
+ RDNS_REQUEST_NEW = 0,
+ RDNS_REQUEST_REGISTERED = 1,
+ RDNS_REQUEST_WAIT_SEND,
+ RDNS_REQUEST_WAIT_REPLY,
+ RDNS_REQUEST_REPLIED,
+ RDNS_REQUEST_FAKE,
+ RDNS_REQUEST_ERROR,
+ RDNS_REQUEST_TCP,
+};
+
+struct rdns_request {
+ struct rdns_resolver *resolver;
+ struct rdns_async_context *async;
+ struct rdns_io_channel *io;
+ struct rdns_reply *reply;
+ enum rdns_request_type type;
+
+ double timeout;
+ unsigned int retransmits;
+
+ int id;
+ struct rdns_request_name *requested_names;
+ unsigned int qcount;
+ enum rdns_request_state state;
+
+ uint8_t *packet;
+ off_t pos;
+ unsigned int packet_len;
+
+ dns_callback_type func;
+ void *arg;
+
+ void *async_event;
+
+#if defined(TWEETNACL) || defined(USE_RSPAMD_CRYPTOBOX)
+ void *curve_plugin_data;
+#endif
+
+ ref_entry_t ref;
+};
+
+
+enum rdns_io_channel_flags {
+ RDNS_CHANNEL_CONNECTED = 1u << 0u,
+ RDNS_CHANNEL_ACTIVE = 1u << 1u,
+ RDNS_CHANNEL_TCP = 1u << 2u,
+ RDNS_CHANNEL_TCP_CONNECTING = 1u << 3u,
+};
+
+#define IS_CHANNEL_CONNECTED(ioc) (((ioc)->flags & RDNS_CHANNEL_CONNECTED) != 0)
+#define IS_CHANNEL_ACTIVE(ioc) (((ioc)->flags & RDNS_CHANNEL_ACTIVE) != 0)
+#define IS_CHANNEL_TCP(ioc) (((ioc)->flags & RDNS_CHANNEL_TCP) != 0)
+
+/**
+ * Used to chain output DNS requests for a TCP connection
+ */
+struct rdns_tcp_output_chain {
+ uint16_t next_write_size; /* Network byte order! */
+ uint16_t cur_write; /* Cur bytes written including `next_write_size` */
+ unsigned char *write_buf;
+ struct rdns_tcp_output_chain *prev, *next;
+};
+
+/**
+ * Specific stuff for a TCP IO chain
+ */
+struct rdns_tcp_channel {
+ uint16_t next_read_size; /* Network byte order on read, then host byte order */
+ uint16_t cur_read; /* Cur bytes read including `next_read_size` */
+ unsigned char *cur_read_buf;
+ unsigned read_buf_allocated;
+
+ /* Chained set of the planned writes */
+ struct rdns_tcp_output_chain *output_chain;
+ unsigned cur_output_chains;
+
+ void *async_read; /** async read event */
+ void *async_write; /** async write event */
+};
+
+KHASH_DECLARE(rdns_requests_hash, int, struct rdns_request *);
+#define RDNS_IO_CHANNEL_TAG UINT64_C(0xe190a5ba12f094c8)
+/**
+ * IO channel for a specific DNS server
+ */
+struct rdns_io_channel {
+ uint64_t struct_magic; /**< tag for this structure */
+ struct rdns_server *srv;
+ struct rdns_resolver *resolver;
+ struct sockaddr *saddr;
+ socklen_t slen;
+ int sock; /**< persistent socket */
+ int flags; /**< see enum rdns_io_channel_flags */
+ void *async_io; /** async opaque ptr */
+ khash_t(rdns_requests_hash) *requests;
+ /*
+ * For DNS replies parsing we use per-channel structure
+ * which is used for two purposes:
+ * 1) We read the next DNS header
+ * 2) We find the corresponding request (if any)
+ * 3) We read the remaining packet (associated with a request or dangling)
+ * This structure is filled on each read-readiness for an IO channel
+ */
+ struct rdns_tcp_channel *tcp;
+ uint64_t uses;
+ ref_entry_t ref;
+};
+
+struct rdns_fake_reply_idx {
+ enum rdns_request_type type;
+ unsigned len;
+ char request[0];
+};
+
+struct rdns_fake_reply {
+ enum dns_rcode rcode;
+ struct rdns_reply_entry *result;
+ UT_hash_handle hh;
+ struct rdns_fake_reply_idx key;
+};
+
+
+struct rdns_resolver {
+ struct rdns_server *servers;
+ struct rdns_async_context *async; /** async callbacks */
+ void *periodic; /** periodic event for resolver */
+ struct rdns_upstream_context *ups;
+ struct rdns_plugin *curve_plugin;
+ struct rdns_fake_reply *fake_elts;
+
+#ifdef __GNUC__
+ __attribute__((format(printf, 4, 0)))
+#endif
+ rdns_log_function logger;
+ void *log_data;
+ enum rdns_log_level log_level;
+
+ uint64_t max_ioc_uses;
+ void *refresh_ioc_periodic;
+
+ bool async_binded;
+ bool initialized;
+ bool enable_dnssec;
+ int flags;
+ ref_entry_t ref;
+};
+
+struct dns_query;
+
+/* Internal DNS structs */
+
+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_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_class {
+ DNS_C_IN = 1,
+
+ DNS_C_ANY = 255
+};
+/* enum dns_class */
+
+struct dns_query {
+ char *qname;
+ unsigned int qtype :16;
+ unsigned int qclass :16;
+};
+
+enum dns_type {
+ DNS_T_A = RDNS_REQUEST_A,
+ DNS_T_NS = RDNS_REQUEST_NS,
+ DNS_T_CNAME = 5,
+ DNS_T_SOA = RDNS_REQUEST_SOA,
+ DNS_T_PTR = RDNS_REQUEST_PTR,
+ DNS_T_MX = RDNS_REQUEST_MX,
+ DNS_T_TXT = RDNS_REQUEST_TXT,
+ DNS_T_AAAA = RDNS_REQUEST_AAAA,
+ DNS_T_SRV = RDNS_REQUEST_SRV,
+ DNS_T_OPT = 41,
+ DNS_T_SSHFP = 44,
+ DNS_T_TLSA = RDNS_REQUEST_TLSA,
+ DNS_T_SPF = RDNS_REQUEST_SPF,
+ DNS_T_ALL = RDNS_REQUEST_ANY
+};
+/* enum dns_type */
+
+static const char dns_rcodes[][32] = {
+ [RDNS_RC_NOERROR] = "no error",
+ [RDNS_RC_FORMERR] = "query format error",
+ [RDNS_RC_SERVFAIL] = "server fail",
+ [RDNS_RC_NXDOMAIN] = "no records with this name",
+ [RDNS_RC_NOTIMP] = "not implemented",
+ [RDNS_RC_REFUSED] = "query refused",
+ [RDNS_RC_YXDOMAIN] = "YXDOMAIN",
+ [RDNS_RC_YXRRSET] = "YXRRSET",
+ [RDNS_RC_NXRRSET] = "NXRRSET",
+ [RDNS_RC_NOTAUTH] = "not authorized",
+ [RDNS_RC_NOTZONE] = "no such zone",
+ [RDNS_RC_TIMEOUT] = "query timed out",
+ [RDNS_RC_NETERR] = "network error",
+ [RDNS_RC_NOREC] = "requested record is not found"
+};
+
+static const char dns_types[][16] = {
+ [RDNS_REQUEST_A] = "A request",
+ [RDNS_REQUEST_NS] = "NS request",
+ [RDNS_REQUEST_PTR] = "PTR request",
+ [RDNS_REQUEST_MX] = "MX request",
+ [RDNS_REQUEST_TXT] = "TXT request",
+ [RDNS_REQUEST_SRV] = "SRV request",
+ [RDNS_REQUEST_SPF] = "SPF request",
+ [RDNS_REQUEST_AAAA] = "AAAA request",
+ [RDNS_REQUEST_TLSA] = "TLSA request",
+ [RDNS_REQUEST_ANY] = "ANY request"
+};
+
+
+#endif /* DNS_PRIVATE_H_ */