1 /*
2  * Copyright (c) 2009, 2012-2015, 2018 by Farsight Security, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef WDNS_H
18 #define WDNS_H
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 
28 /* Constants. */
29 
30 #define WDNS_LEN_HEADER		12
31 #define WDNS_MAXLEN_NAME	255
32 
33 #define WDNS_MSG_SEC_QUESTION	0
34 #define WDNS_MSG_SEC_ANSWER	1
35 #define WDNS_MSG_SEC_AUTHORITY	2
36 #define WDNS_MSG_SEC_ADDITIONAL	3
37 #define WDNS_MSG_SEC_MAX	4
38 
39 #define WDNS_PRESLEN_NAME	1025
40 #define WDNS_PRESLEN_TYPE_A	16
41 #define WDNS_PRESLEN_TYPE_AAAA	46
42 
43 #define WDNS_OP_QUERY		0
44 #define WDNS_OP_IQUERY		1
45 #define WDNS_OP_STATUS		2
46 #define WDNS_OP_NOTIFY		4
47 #define WDNS_OP_UPDATE		5
48 
49 #define WDNS_R_NOERROR		0
50 #define WDNS_R_FORMERR		1
51 #define WDNS_R_SERVFAIL		2
52 #define WDNS_R_NXDOMAIN		3
53 #define WDNS_R_NOTIMP		4
54 #define WDNS_R_REFUSED		5
55 #define WDNS_R_YXDOMAIN		6
56 #define WDNS_R_YXRRSET		7
57 #define WDNS_R_NXRRSET		8
58 #define WDNS_R_NOTAUTH		9
59 #define WDNS_R_NOTZONE		10
60 #define WDNS_R_BADVERS		16
61 
62 #define WDNS_CLASS_IN		1
63 #define WDNS_CLASS_CH		3
64 #define WDNS_CLASS_HS		4
65 #define WDNS_CLASS_NONE		254
66 #define WDNS_CLASS_ANY		255
67 
68 #define WDNS_TYPE_A		1
69 #define WDNS_TYPE_NS		2
70 #define WDNS_TYPE_MD		3
71 #define WDNS_TYPE_MF		4
72 #define WDNS_TYPE_CNAME		5
73 #define WDNS_TYPE_SOA		6
74 #define WDNS_TYPE_MB		7
75 #define WDNS_TYPE_MG		8
76 #define WDNS_TYPE_MR		9
77 #define WDNS_TYPE_NULL		10
78 #define WDNS_TYPE_WKS		11
79 #define WDNS_TYPE_PTR		12
80 #define WDNS_TYPE_HINFO		13
81 #define WDNS_TYPE_MINFO		14
82 #define WDNS_TYPE_MX		15
83 #define WDNS_TYPE_TXT		16
84 #define WDNS_TYPE_RP		17
85 #define WDNS_TYPE_AFSDB		18
86 #define WDNS_TYPE_X25		19
87 #define WDNS_TYPE_ISDN		20
88 #define WDNS_TYPE_RT		21
89 #define WDNS_TYPE_NSAP		22
90 #define WDNS_TYPE_NSAP_PTR	23
91 #define WDNS_TYPE_SIG		24
92 #define WDNS_TYPE_KEY		25
93 #define WDNS_TYPE_PX		26
94 #define WDNS_TYPE_GPOS		27
95 #define WDNS_TYPE_AAAA		28
96 #define WDNS_TYPE_LOC		29
97 #define WDNS_TYPE_NXT		30
98 #define WDNS_TYPE_EID		31
99 #define WDNS_TYPE_NIMLOC	32
100 #define WDNS_TYPE_SRV		33
101 #define WDNS_TYPE_ATMA		34
102 #define WDNS_TYPE_NAPTR		35
103 #define WDNS_TYPE_KX		36
104 #define WDNS_TYPE_CERT		37
105 #define WDNS_TYPE_A6		38
106 #define WDNS_TYPE_DNAME		39
107 #define WDNS_TYPE_SINK		40
108 #define WDNS_TYPE_OPT		41
109 #define WDNS_TYPE_APL		42
110 #define WDNS_TYPE_DS		43
111 #define WDNS_TYPE_SSHFP		44
112 #define WDNS_TYPE_IPSECKEY	45
113 #define WDNS_TYPE_RRSIG		46
114 #define WDNS_TYPE_NSEC		47
115 #define WDNS_TYPE_DNSKEY	48
116 #define WDNS_TYPE_DHCID		49
117 #define WDNS_TYPE_NSEC3		50
118 #define WDNS_TYPE_NSEC3PARAM	51
119 #define WDNS_TYPE_TLSA		52
120 /* Unassigned: 53 - 54 */
121 #define WDNS_TYPE_HIP		55
122 #define WDNS_TYPE_NINFO		56
123 #define WDNS_TYPE_RKEY		57
124 #define WDNS_TYPE_TALINK	58
125 #define WDNS_TYPE_CDS		59
126 #define WDNS_TYPE_CDNSKEY	60
127 #define WDNS_TYPE_OPENPGPKEY	61
128 #define WDNS_TYPE_CSYNC		62
129 /* Unassigned: 63 - 98 */
130 #define WDNS_TYPE_SPF		99
131 #define WDNS_TYPE_UINFO		100
132 #define WDNS_TYPE_UID		101
133 #define WDNS_TYPE_GID		102
134 #define WDNS_TYPE_UNSPEC	103
135 #define WDNS_TYPE_NID		104
136 #define WDNS_TYPE_L32		105
137 #define WDNS_TYPE_L64		106
138 #define WDNS_TYPE_LP		107
139 #define WDNS_TYPE_EUI48		108
140 #define WDNS_TYPE_EUI64		109
141 /* Unassigned: 110 - 248 */
142 #define WDNS_TYPE_TKEY		249
143 #define WDNS_TYPE_TSIG		250
144 #define WDNS_TYPE_IXFR		251
145 #define WDNS_TYPE_AXFR		252
146 #define WDNS_TYPE_MAILB		253
147 #define WDNS_TYPE_MAILA		254
148 #define WDNS_TYPE_ANY		255
149 #define WDNS_TYPE_URI		256
150 #define WDNS_TYPE_CAA		257
151 /* Unassigned: 258 - 32767 */
152 #define WDNS_TYPE_TA		32768
153 #define WDNS_TYPE_DLV		32769
154 /* Unassigned: 32770 - 65279 */
155 /* Private use: 65280 - 65534 */
156 /* Reserved: 65535 */
157 
158 #define WDNS_LIBRARY_VERSION "0.10.0"
159 #define WDNS_LIBRARY_VERSION_NUMBER 0 * 1000000L + 10 * 1000L + 0
160 
161 /* Macros. */
162 
163 #define WDNS_FLAGS_QR(msg)		((((msg).flags) >> 15) & 0x01)
164 #define WDNS_FLAGS_OPCODE(msg)		((((msg).flags) >> 11) & 0x0f)
165 #define WDNS_FLAGS_AA(msg)		((((msg).flags) >> 10) & 0x01)
166 #define WDNS_FLAGS_TC(msg)		((((msg).flags) >> 9) & 0x01)
167 #define WDNS_FLAGS_RD(msg)		((((msg).flags) >> 8) & 0x01)
168 #define WDNS_FLAGS_RA(msg)		((((msg).flags) >> 7) & 0x01)
169 #define WDNS_FLAGS_Z(msg)		((((msg).flags) >> 6) & 0x01)
170 #define WDNS_FLAGS_AD(msg)		((((msg).flags) >> 5) & 0x01)
171 #define WDNS_FLAGS_CD(msg)		((((msg).flags) >> 4) & 0x01)
172 #define WDNS_FLAGS_RCODE(msg)		((msg).rcode)
173 
174 #if defined(__GNUC__)
175 # define WDNS_WARN_UNUSED_RESULT	__attribute__ ((warn_unused_result))
176 #else
177 # define WDNS_WARN_UNUSED_RESULT
178 #endif
179 
180 /* Data structures and definitions. */
181 
182 typedef enum {
183 	wdns_res_success,
184 	wdns_res_failure,
185 	wdns_res_invalid_compression_pointer,
186 	wdns_res_invalid_length_octet,
187 	wdns_res_invalid_opcode,
188 	wdns_res_invalid_rcode,
189 	wdns_res_len,
190 	wdns_res_malloc,
191 	wdns_res_name_len,
192 	wdns_res_name_overflow,
193 	wdns_res_out_of_bounds,
194 	wdns_res_overflow,
195 	wdns_res_parse_error,
196 	wdns_res_qdcount,
197 	wdns_res_unknown_opcode,
198 	wdns_res_unknown_rcode,
199 } wdns_res;
200 
201 typedef struct {
202 	uint8_t			len;
203 	uint8_t			*data;
204 } wdns_name_t;
205 
206 typedef struct {
207 	uint16_t		len;
208 	uint8_t			data[];
209 } wdns_rdata_t;
210 
211 typedef struct {
212 	uint32_t		rrttl;
213 	uint16_t		rrtype;
214 	uint16_t		rrclass;
215 	wdns_name_t		name;
216 	wdns_rdata_t		*rdata;
217 } wdns_rr_t;
218 
219 typedef struct {
220 	uint32_t		rrttl;
221 	uint16_t		rrtype;
222 	uint16_t		rrclass;
223 	uint16_t		n_rdatas;
224 	wdns_name_t		name;
225 	wdns_rdata_t		**rdatas;
226 } wdns_rrset_t;
227 
228 typedef struct {
229 	uint16_t		n_rrs;
230 	uint16_t		n_rrsets;
231 	wdns_rr_t		*rrs;
232 	wdns_rrset_t		*rrsets;
233 } wdns_rrset_array_t;
234 
235 typedef struct {
236 	bool			present;
237 	uint8_t			version;
238 	uint16_t		flags;
239 	uint16_t		size;
240 	wdns_rdata_t		*options;
241 } wdns_edns_t;
242 
243 typedef struct {
244 	wdns_rrset_array_t	sections[4];
245 	wdns_edns_t		edns;
246 	uint16_t		id;
247 	uint16_t		flags;
248 	uint16_t		rcode;
249 } wdns_message_t;
250 
251 /* Function prototypes. */
252 
253 typedef void (*wdns_callback_name)(wdns_name_t *name, void *user);
254 
255 /* Functions for converting objects to presentation format strings. */
256 
257 const char *	wdns_res_to_str(wdns_res res);
258 const char *	wdns_opcode_to_str(uint16_t dns_opcode);
259 const char *	wdns_rcode_to_str(uint16_t dns_rcode);
260 const char *	wdns_rrclass_to_str(uint16_t dns_class);
261 const char *	wdns_rrtype_to_str(uint16_t dns_type);
262 size_t		wdns_domain_to_str(const uint8_t *src, size_t src_len, char *dst);
263 
264 char *		wdns_message_to_str(wdns_message_t *m);
265 char *		wdns_rrset_array_to_str(wdns_rrset_array_t *a, unsigned sec);
266 char *		wdns_rrset_to_str(wdns_rrset_t *rrset, unsigned sec);
267 char *		wdns_rr_to_str(wdns_rr_t *rr, unsigned sec);
268 char *		wdns_rdata_to_str(const uint8_t *rdata, uint16_t rdlen,
269 				  uint16_t rrtype, uint16_t rrclass);
270 
271 /* Functions for converting presentation format strings to objects. */
272 
273 WDNS_WARN_UNUSED_RESULT
274 wdns_res
275 wdns_str_to_name(const char *str, wdns_name_t *name);
276 
277 WDNS_WARN_UNUSED_RESULT
278 wdns_res
279 wdns_str_to_name_case(const char *str, wdns_name_t *name);
280 
281 wdns_res
282 wdns_str_to_rcode(const char *str, uint16_t *out);
283 
284 uint16_t
285 wdns_str_to_rrtype(const char *str);
286 
287 uint16_t
288 wdns_str_to_rrclass(const char *str);
289 
290 wdns_res
291 wdns_str_to_rdata(const char * str, uint16_t rrtype, uint16_t rrclass,
292 		   uint8_t **rdata, size_t *rdlen);
293 
294 /* Comparison functions. */
295 
296 bool	wdns_compare_rr_rrset(const wdns_rr_t *rr, const wdns_rrset_t *rrset);
297 
298 /* Functions for clearing wdns objects. */
299 
300 void	wdns_clear_message(wdns_message_t *m);
301 void	wdns_clear_rr(wdns_rr_t *rr);
302 void	wdns_clear_rrset(wdns_rrset_t *rrset);
303 void	wdns_clear_rrset_array(wdns_rrset_array_t *a);
304 
305 /* Functions for printing formatted output. */
306 
307 void	wdns_print_message(FILE *fp, wdns_message_t *m);
308 void	wdns_print_rr(FILE *fp, wdns_rr_t *rr, unsigned sec);
309 void	wdns_print_rrset(FILE *fp, wdns_rrset_t *rrset, unsigned sec);
310 void	wdns_print_rrset_array(FILE *fp, wdns_rrset_array_t *a, unsigned sec);
311 
312 /* Utility functions. */
313 
314 size_t	wdns_skip_name(const uint8_t **data, const uint8_t *eod);
315 
316 wdns_res
317 wdns_copy_uname(const uint8_t *p, const uint8_t *eop, const uint8_t *src,
318 		uint8_t *dst, size_t *sz);
319 
320 wdns_res
321 wdns_len_uname(const uint8_t *p, const uint8_t *eop, size_t *sz);
322 
323 wdns_res
324 wdns_sort_rrset(wdns_rrset_t *);
325 
326 wdns_res
327 wdns_unpack_name(const uint8_t *p, const uint8_t *eop, const uint8_t *src,
328 		 uint8_t *dst, size_t *sz);
329 
330 wdns_res
331 wdns_count_labels(wdns_name_t *name, size_t *nlabels);
332 
333 wdns_res
334 wdns_is_subdomain(wdns_name_t *n0, wdns_name_t *n1, bool *is_subdomain);
335 
336 wdns_res
337 wdns_file_load_names(const char *fname, wdns_callback_name cb, void *user);
338 
339 wdns_res
340 wdns_left_chop(wdns_name_t *name, wdns_name_t *chop);
341 
342 WDNS_WARN_UNUSED_RESULT
343 wdns_res
344 wdns_reverse_name(const uint8_t *name, size_t len_name, uint8_t *rev_name);
345 
346 /**
347  * Retrieve the semantic library version as a string. This function was
348  * Introduced in version 0.10.0.
349  */
350 const char *wdns_get_version(void);
351 
352 /**
353  * Retrieve the semantic library version as a packed integer. The number is a
354  * combination of the major, minor, and patchelevel numbers as per:
355  * MAJOR * 1000000 + MINOR * 1000 + PATCHLEVEL. This function was introduced
356  * in version 0.10.0.
357  */
358 uint32_t wdns_get_version_number(void);
359 
360 /* Parsing functions. */
361 
362 wdns_res
363 wdns_parse_message(wdns_message_t *m, const uint8_t *pkt, size_t len);
364 
365 /* Deserialization functions. */
366 
367 wdns_res
368 wdns_deserialize_rrset(wdns_rrset_t *rrset, const uint8_t *buf, size_t sz);
369 
370 /* Serialization functions. */
371 
372 wdns_res
373 wdns_serialize_rrset(const wdns_rrset_t *rrset, uint8_t *buf, size_t *sz);
374 
375 /* Downcasing functions. */
376 
377 void
378 wdns_downcase_name(wdns_name_t *name);
379 
380 wdns_res
381 wdns_downcase_rdata(wdns_rdata_t *rdata, uint16_t rrtype, uint16_t rrclass);
382 
383 wdns_res
384 wdns_downcase_rrset(wdns_rrset_t *rrset);
385 
386 #ifdef __cplusplus
387 }
388 #endif
389 
390 #endif /* WDNS_H */
391