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 
24 #ifndef DNS_PRIVATE_H_
25 #define DNS_PRIVATE_H_
26 
27 #include "config.h"
28 #include "uthash.h"
29 #include "utlist.h"
30 #include "rdns.h"
31 #include "upstream.h"
32 #include "ref.h"
33 
34 static const int dns_port = 53;
35 static const int default_io_cnt = 8;
36 
37 #define UDP_PACKET_SIZE 4096
38 
39 #define DNS_COMPRESSION_BITS 0xC0
40 
41 #define DNS_D_MAXLABEL  63      /* + 1 '\0' */
42 #define DNS_D_MAXNAME   255     /* + 1 '\0' */
43 
44 #define RESOLV_CONF "/etc/resolv.conf"
45 
46 /**
47  * Represents DNS server
48  */
49 struct rdns_server {
50 	char *name;
51 	unsigned int port;
52 	unsigned int io_cnt;
53 
54 	struct rdns_io_channel **io_channels;
55 	void *ups_elt;
56 	upstream_entry_t up;
57 };
58 
59 enum rdns_request_state {
60 	RDNS_REQUEST_NEW = 0,
61 	RDNS_REQUEST_REGISTERED = 1,
62 	RDNS_REQUEST_WAIT_SEND,
63 	RDNS_REQUEST_WAIT_REPLY,
64 	RDNS_REQUEST_REPLIED,
65 	RDNS_REQUEST_FAKE,
66 };
67 
68 struct rdns_request {
69 	struct rdns_resolver *resolver;
70 	struct rdns_async_context *async;
71 	struct rdns_io_channel *io;
72 	struct rdns_reply *reply;
73 	enum rdns_request_type type;
74 
75 	double timeout;
76 	unsigned int retransmits;
77 
78 	int id;
79 	struct rdns_request_name *requested_names;
80 	unsigned int qcount;
81 	enum rdns_request_state state;
82 
83 	uint8_t *packet;
84 	off_t pos;
85 	unsigned int packet_len;
86 
87 	dns_callback_type func;
88 	void *arg;
89 
90 	void *async_event;
91 
92 #if defined(TWEETNACL) || defined(USE_RSPAMD_CRYPTOBOX)
93 	void *curve_plugin_data;
94 #endif
95 
96 	UT_hash_handle hh;
97 	ref_entry_t ref;
98 };
99 
100 
101 /**
102  * IO channel for a specific DNS server
103  */
104 struct rdns_io_channel {
105 	struct rdns_server *srv;
106 	struct rdns_resolver *resolver;
107 	struct sockaddr *saddr;
108 	socklen_t slen;
109 	int sock; /**< persistent socket                                          */
110 	bool active;
111 	bool connected;
112 	void *async_io; /** async opaque ptr */
113 	struct rdns_request *requests; /**< requests in flight                                         */
114 	uint64_t uses;
115 	ref_entry_t ref;
116 };
117 
118 struct rdns_fake_reply_idx {
119 	enum rdns_request_type type;
120 	unsigned len;
121 	char request[0];
122 };
123 
124 struct rdns_fake_reply {
125 	enum dns_rcode rcode;
126 	struct rdns_reply_entry *result;
127 	UT_hash_handle hh;
128 	struct rdns_fake_reply_idx key;
129 };
130 
131 
132 struct rdns_resolver {
133 	struct rdns_server *servers;
134 	struct rdns_io_channel *io_channels; /**< hash of io chains indexed by socket        */
135 	struct rdns_async_context *async; /** async callbacks */
136 	void *periodic; /** periodic event for resolver */
137 	struct rdns_upstream_context *ups;
138 	struct rdns_plugin *curve_plugin;
139 	struct rdns_fake_reply *fake_elts;
140 
141 #ifdef __GNUC__
142 	__attribute__((format(printf, 4, 0)))
143 #endif
144 	rdns_log_function logger;
145 	void *log_data;
146 	enum rdns_log_level log_level;
147 
148 	uint64_t max_ioc_uses;
149 	void *refresh_ioc_periodic;
150 
151 	bool async_binded;
152 	bool initialized;
153 	bool enable_dnssec;
154 	int flags;
155 	ref_entry_t ref;
156 };
157 
158 struct dns_header;
159 struct dns_query;
160 
161 /* Internal DNS structs */
162 
163 struct dns_header {
164 	unsigned int qid :16;
165 
166 #if BYTE_ORDER == BIG_ENDIAN
167 	unsigned int qr:1;
168 	unsigned int opcode:4;
169 	unsigned int aa:1;
170 	unsigned int tc:1;
171 	unsigned int rd:1;
172 
173 	unsigned int ra:1;
174 	unsigned int cd : 1;
175 	unsigned int ad : 1;
176 	unsigned int z : 1;
177 	unsigned int rcode:4;
178 #else
179 	unsigned int rd :1;
180 	unsigned int tc :1;
181 	unsigned int aa :1;
182 	unsigned int opcode :4;
183 	unsigned int qr :1;
184 
185 	unsigned int rcode :4;
186 	unsigned int z : 1;
187 	unsigned int ad : 1;
188 	unsigned int cd : 1;
189 	unsigned int ra :1;
190 #endif
191 
192 	unsigned int qdcount :16;
193 	unsigned int ancount :16;
194 	unsigned int nscount :16;
195 	unsigned int arcount :16;
196 };
197 
198 enum dns_section {
199 	DNS_S_QD = 0x01,
200 #define DNS_S_QUESTION          DNS_S_QD
201 
202 	DNS_S_AN = 0x02,
203 #define DNS_S_ANSWER            DNS_S_AN
204 
205 	DNS_S_NS = 0x04,
206 #define DNS_S_AUTHORITY         DNS_S_NS
207 
208 	DNS_S_AR = 0x08,
209 #define DNS_S_ADDITIONAL        DNS_S_AR
210 
211 	DNS_S_ALL = 0x0f
212 };
213 /* enum dns_section */
214 
215 enum dns_opcode {
216 	DNS_OP_QUERY = 0,
217 	DNS_OP_IQUERY = 1,
218 	DNS_OP_STATUS = 2,
219 	DNS_OP_NOTIFY = 4,
220 	DNS_OP_UPDATE = 5,
221 };
222 /* dns_opcode */
223 
224 enum dns_class {
225 	DNS_C_IN = 1,
226 
227 	DNS_C_ANY = 255
228 };
229 /* enum dns_class */
230 
231 struct dns_query {
232 	char *qname;
233 	unsigned int qtype :16;
234 	unsigned int qclass :16;
235 };
236 
237 enum dns_type {
238 	DNS_T_A = RDNS_REQUEST_A,
239 	DNS_T_NS = RDNS_REQUEST_NS,
240 	DNS_T_CNAME = 5,
241 	DNS_T_SOA = RDNS_REQUEST_SOA,
242 	DNS_T_PTR = RDNS_REQUEST_PTR,
243 	DNS_T_MX = RDNS_REQUEST_MX,
244 	DNS_T_TXT = RDNS_REQUEST_TXT,
245 	DNS_T_AAAA = RDNS_REQUEST_AAAA,
246 	DNS_T_SRV = RDNS_REQUEST_SRV,
247 	DNS_T_OPT = 41,
248 	DNS_T_SSHFP = 44,
249 	DNS_T_TLSA = RDNS_REQUEST_TLSA,
250 	DNS_T_SPF = RDNS_REQUEST_SPF,
251 	DNS_T_ALL = RDNS_REQUEST_ANY
252 };
253 /* enum dns_type */
254 
255 static const char dns_rcodes[][32] = {
256 	[RDNS_RC_NOERROR]  = "no error",
257 	[RDNS_RC_FORMERR]  = "query format error",
258 	[RDNS_RC_SERVFAIL] = "server fail",
259 	[RDNS_RC_NXDOMAIN] = "no records with this name",
260 	[RDNS_RC_NOTIMP]   = "not implemented",
261 	[RDNS_RC_REFUSED]  = "query refused",
262 	[RDNS_RC_YXDOMAIN] = "YXDOMAIN",
263 	[RDNS_RC_YXRRSET]  = "YXRRSET",
264 	[RDNS_RC_NXRRSET]  = "NXRRSET",
265 	[RDNS_RC_NOTAUTH]  = "not authorized",
266 	[RDNS_RC_NOTZONE]  = "no such zone",
267 	[RDNS_RC_TIMEOUT]  = "query timed out",
268 	[RDNS_RC_NETERR]  = "network error",
269 	[RDNS_RC_NOREC]  = "requested record is not found"
270 };
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 
285 
286 #endif /* DNS_PRIVATE_H_ */
287