You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dns_private.h 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /* Copyright (c) 2014, Vsevolod Stakhov
  2. * All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. *
  12. * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
  13. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  16. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  18. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  19. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  21. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. #ifndef DNS_PRIVATE_H_
  24. #define DNS_PRIVATE_H_
  25. #include "config.h"
  26. #include "uthash.h"
  27. #include "utlist.h"
  28. #include "khash.h"
  29. #include "rdns.h"
  30. #include "upstream.h"
  31. #include "ref.h"
  32. static const int dns_port = 53;
  33. static const int default_io_cnt = 8;
  34. static const int default_tcp_io_cnt = 1;
  35. #define UDP_PACKET_SIZE (4096)
  36. #define DNS_COMPRESSION_BITS 0xC0
  37. #define DNS_D_MAXLABEL 63 /* + 1 '\0' */
  38. #define DNS_D_MAXNAME 255 /* + 1 '\0' */
  39. #define RESOLV_CONF "/etc/resolv.conf"
  40. struct dns_header {
  41. unsigned int qid :16;
  42. #if BYTE_ORDER == BIG_ENDIAN
  43. unsigned int qr:1;
  44. unsigned int opcode:4;
  45. unsigned int aa:1;
  46. unsigned int tc:1;
  47. unsigned int rd:1;
  48. unsigned int ra:1;
  49. unsigned int cd : 1;
  50. unsigned int ad : 1;
  51. unsigned int z : 1;
  52. unsigned int rcode:4;
  53. #else
  54. unsigned int rd :1;
  55. unsigned int tc :1;
  56. unsigned int aa :1;
  57. unsigned int opcode :4;
  58. unsigned int qr :1;
  59. unsigned int rcode :4;
  60. unsigned int z : 1;
  61. unsigned int ad : 1;
  62. unsigned int cd : 1;
  63. unsigned int ra :1;
  64. #endif
  65. unsigned int qdcount :16;
  66. unsigned int ancount :16;
  67. unsigned int nscount :16;
  68. unsigned int arcount :16;
  69. };
  70. /**
  71. * Represents DNS server
  72. */
  73. struct rdns_server {
  74. char *name;
  75. unsigned int port;
  76. unsigned int io_cnt;
  77. unsigned int tcp_io_cnt;
  78. struct rdns_io_channel **io_channels;
  79. struct rdns_io_channel **tcp_io_channels;
  80. void *ups_elt;
  81. upstream_entry_t up;
  82. };
  83. enum rdns_request_state {
  84. RDNS_REQUEST_NEW = 0,
  85. RDNS_REQUEST_REGISTERED = 1,
  86. RDNS_REQUEST_WAIT_SEND,
  87. RDNS_REQUEST_WAIT_REPLY,
  88. RDNS_REQUEST_REPLIED,
  89. RDNS_REQUEST_FAKE,
  90. RDNS_REQUEST_ERROR,
  91. RDNS_REQUEST_TCP,
  92. };
  93. struct rdns_request {
  94. struct rdns_resolver *resolver;
  95. struct rdns_async_context *async;
  96. struct rdns_io_channel *io;
  97. struct rdns_reply *reply;
  98. enum rdns_request_type type;
  99. double timeout;
  100. unsigned int retransmits;
  101. int id;
  102. struct rdns_request_name *requested_names;
  103. unsigned int qcount;
  104. enum rdns_request_state state;
  105. uint8_t *packet;
  106. off_t pos;
  107. unsigned int packet_len;
  108. dns_callback_type func;
  109. void *arg;
  110. void *async_event;
  111. #if defined(TWEETNACL) || defined(USE_RSPAMD_CRYPTOBOX)
  112. void *curve_plugin_data;
  113. #endif
  114. ref_entry_t ref;
  115. };
  116. enum rdns_io_channel_flags {
  117. RDNS_CHANNEL_CONNECTED = 1u << 0u,
  118. RDNS_CHANNEL_ACTIVE = 1u << 1u,
  119. RDNS_CHANNEL_TCP = 1u << 2u,
  120. RDNS_CHANNEL_TCP_CONNECTING = 1u << 3u,
  121. };
  122. #define IS_CHANNEL_CONNECTED(ioc) (((ioc)->flags & RDNS_CHANNEL_CONNECTED) != 0)
  123. #define IS_CHANNEL_ACTIVE(ioc) (((ioc)->flags & RDNS_CHANNEL_ACTIVE) != 0)
  124. #define IS_CHANNEL_TCP(ioc) (((ioc)->flags & RDNS_CHANNEL_TCP) != 0)
  125. /**
  126. * Used to chain output DNS requests for a TCP connection
  127. */
  128. struct rdns_tcp_output_chain {
  129. uint16_t next_write_size; /* Network byte order! */
  130. uint16_t cur_write; /* Cur bytes written including `next_write_size` */
  131. unsigned char *write_buf;
  132. struct rdns_tcp_output_chain *prev, *next;
  133. };
  134. /**
  135. * Specific stuff for a TCP IO chain
  136. */
  137. struct rdns_tcp_channel {
  138. uint16_t next_read_size; /* Network byte order on read, then host byte order */
  139. uint16_t cur_read; /* Cur bytes read including `next_read_size` */
  140. unsigned char *cur_read_buf;
  141. unsigned read_buf_allocated;
  142. /* Chained set of the planned writes */
  143. struct rdns_tcp_output_chain *output_chain;
  144. unsigned cur_output_chains;
  145. void *async_read; /** async read event */
  146. void *async_write; /** async write event */
  147. };
  148. KHASH_DECLARE(rdns_requests_hash, int, struct rdns_request *);
  149. #define RDNS_IO_CHANNEL_TAG UINT64_C(0xe190a5ba12f094c8)
  150. /**
  151. * IO channel for a specific DNS server
  152. */
  153. struct rdns_io_channel {
  154. uint64_t struct_magic; /**< tag for this structure */
  155. struct rdns_server *srv;
  156. struct rdns_resolver *resolver;
  157. struct sockaddr *saddr;
  158. socklen_t slen;
  159. int sock; /**< persistent socket */
  160. int flags; /**< see enum rdns_io_channel_flags */
  161. void *async_io; /** async opaque ptr */
  162. khash_t(rdns_requests_hash) *requests;
  163. /*
  164. * For DNS replies parsing we use per-channel structure
  165. * which is used for two purposes:
  166. * 1) We read the next DNS header
  167. * 2) We find the corresponding request (if any)
  168. * 3) We read the remaining packet (associated with a request or dangling)
  169. * This structure is filled on each read-readiness for an IO channel
  170. */
  171. struct rdns_tcp_channel *tcp;
  172. uint64_t uses;
  173. ref_entry_t ref;
  174. };
  175. struct rdns_fake_reply_idx {
  176. enum rdns_request_type type;
  177. unsigned len;
  178. char request[0];
  179. };
  180. struct rdns_fake_reply {
  181. enum dns_rcode rcode;
  182. struct rdns_reply_entry *result;
  183. UT_hash_handle hh;
  184. struct rdns_fake_reply_idx key;
  185. };
  186. struct rdns_resolver {
  187. struct rdns_server *servers;
  188. struct rdns_async_context *async; /** async callbacks */
  189. void *periodic; /** periodic event for resolver */
  190. struct rdns_upstream_context *ups;
  191. struct rdns_plugin *curve_plugin;
  192. struct rdns_fake_reply *fake_elts;
  193. #ifdef __GNUC__
  194. __attribute__((format(printf, 4, 0)))
  195. #endif
  196. rdns_log_function logger;
  197. void *log_data;
  198. enum rdns_log_level log_level;
  199. uint64_t max_ioc_uses;
  200. void *refresh_ioc_periodic;
  201. bool async_binded;
  202. bool initialized;
  203. bool enable_dnssec;
  204. int flags;
  205. ref_entry_t ref;
  206. };
  207. struct dns_query;
  208. /* Internal DNS structs */
  209. enum dns_section {
  210. DNS_S_QD = 0x01,
  211. #define DNS_S_QUESTION DNS_S_QD
  212. DNS_S_AN = 0x02,
  213. #define DNS_S_ANSWER DNS_S_AN
  214. DNS_S_NS = 0x04,
  215. #define DNS_S_AUTHORITY DNS_S_NS
  216. DNS_S_AR = 0x08,
  217. #define DNS_S_ADDITIONAL DNS_S_AR
  218. DNS_S_ALL = 0x0f
  219. };
  220. /* enum dns_section */
  221. enum dns_opcode {
  222. DNS_OP_QUERY = 0,
  223. DNS_OP_IQUERY = 1,
  224. DNS_OP_STATUS = 2,
  225. DNS_OP_NOTIFY = 4,
  226. DNS_OP_UPDATE = 5,
  227. };
  228. /* dns_opcode */
  229. enum dns_class {
  230. DNS_C_IN = 1,
  231. DNS_C_ANY = 255
  232. };
  233. /* enum dns_class */
  234. struct dns_query {
  235. char *qname;
  236. unsigned int qtype :16;
  237. unsigned int qclass :16;
  238. };
  239. enum dns_type {
  240. DNS_T_A = RDNS_REQUEST_A,
  241. DNS_T_NS = RDNS_REQUEST_NS,
  242. DNS_T_CNAME = 5,
  243. DNS_T_SOA = RDNS_REQUEST_SOA,
  244. DNS_T_PTR = RDNS_REQUEST_PTR,
  245. DNS_T_MX = RDNS_REQUEST_MX,
  246. DNS_T_TXT = RDNS_REQUEST_TXT,
  247. DNS_T_AAAA = RDNS_REQUEST_AAAA,
  248. DNS_T_SRV = RDNS_REQUEST_SRV,
  249. DNS_T_OPT = 41,
  250. DNS_T_SSHFP = 44,
  251. DNS_T_TLSA = RDNS_REQUEST_TLSA,
  252. DNS_T_SPF = RDNS_REQUEST_SPF,
  253. DNS_T_ALL = RDNS_REQUEST_ANY
  254. };
  255. /* enum dns_type */
  256. static const char dns_rcodes[][32] = {
  257. [RDNS_RC_NOERROR] = "no error",
  258. [RDNS_RC_FORMERR] = "query format error",
  259. [RDNS_RC_SERVFAIL] = "server fail",
  260. [RDNS_RC_NXDOMAIN] = "no records with this name",
  261. [RDNS_RC_NOTIMP] = "not implemented",
  262. [RDNS_RC_REFUSED] = "query refused",
  263. [RDNS_RC_YXDOMAIN] = "YXDOMAIN",
  264. [RDNS_RC_YXRRSET] = "YXRRSET",
  265. [RDNS_RC_NXRRSET] = "NXRRSET",
  266. [RDNS_RC_NOTAUTH] = "not authorized",
  267. [RDNS_RC_NOTZONE] = "no such zone",
  268. [RDNS_RC_TIMEOUT] = "query timed out",
  269. [RDNS_RC_NETERR] = "network error",
  270. [RDNS_RC_NOREC] = "requested record is not found"
  271. };
  272. static const char dns_types[][16] = {
  273. [RDNS_REQUEST_A] = "A request",
  274. [RDNS_REQUEST_NS] = "NS request",
  275. [RDNS_REQUEST_PTR] = "PTR request",
  276. [RDNS_REQUEST_MX] = "MX request",
  277. [RDNS_REQUEST_TXT] = "TXT request",
  278. [RDNS_REQUEST_SRV] = "SRV request",
  279. [RDNS_REQUEST_SPF] = "SPF request",
  280. [RDNS_REQUEST_AAAA] = "AAAA request",
  281. [RDNS_REQUEST_TLSA] = "TLSA request",
  282. [RDNS_REQUEST_ANY] = "ANY request"
  283. };
  284. #endif /* DNS_PRIVATE_H_ */