123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- /* 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_ */
|