1 /*
2  * include/types/dns.h
3  * This file provides structures and types for DNS.
4  *
5  * Copyright (C) 2014 Baptiste Assmann <bedis9@gmail.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation, version 2.1
10  * exclusively.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #ifndef _TYPES_DNS_H
23 #define _TYPES_DNS_H
24 
25 /*DNS maximum values */
26 /*
27  * Maximum issued from RFC:
28  *  RFC 1035: https://www.ietf.org/rfc/rfc1035.txt chapter 2.3.4
29  *  RFC 2671: http://tools.ietf.org/html/rfc2671
30  */
31 #define DNS_MAX_LABEL_SIZE	63
32 #define DNS_MAX_NAME_SIZE	255
33 #define DNS_MAX_UDP_MESSAGE	512
34 
35 /* DNS minimun record size: 1 char + 1 NULL + type + class */
36 #define DNS_MIN_RECORD_SIZE	( 1 + 1 + 2 + 2 )
37 
38 /* maximum number of query records in a DNS response
39  * For now, we allow only one */
40 #define DNS_MAX_QUERY_RECORDS 1
41 
42 /* maximum number of answer record in a DNS response */
43 #define DNS_MAX_ANSWER_RECORDS ((DNS_MAX_UDP_MESSAGE - DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE)
44 
45 /* size of dns_buffer used to store responses from the buffer
46  * dns_buffer is used to store data collected from records found in a response.
47  * Before using it, caller will always check that there is at least DNS_MAX_NAME_SIZE bytes
48  * available */
49 #define DNS_ANALYZE_BUFFER_SIZE DNS_MAX_UDP_MESSAGE + DNS_MAX_NAME_SIZE
50 
51 /* DNS error messages */
52 #define DNS_TOO_LONG_FQDN	"hostname too long"
53 #define DNS_LABEL_TOO_LONG	"one label too long"
54 #define DNS_INVALID_CHARACTER	"found an invalid character"
55 
56 /* dns query class */
57 #define DNS_RCLASS_IN		1	/* internet class */
58 
59 /* dns record types (non exhaustive list) */
60 #define DNS_RTYPE_A		1	/* IPv4 address */
61 #define DNS_RTYPE_CNAME		5	/* canonical name */
62 #define DNS_RTYPE_AAAA		28	/* IPv6 address */
63 #define DNS_RTYPE_ANY		255	/* all records */
64 
65 /* dns rcode values */
66 #define DNS_RCODE_NO_ERROR	0	/* no error */
67 #define DNS_RCODE_NX_DOMAIN	3	/* non existent domain */
68 #define DNS_RCODE_REFUSED	5	/* query refused */
69 
70 /* dns flags masks */
71 #define DNS_FLAG_TRUNCATED	0x0200	/* mask for truncated flag */
72 #define DNS_FLAG_REPLYCODE	0x000F	/* mask for reply code */
73 
74 /* max number of network preference entries are avalaible from the
75  * configuration file.
76  */
77 #define SRV_MAX_PREF_NET 5
78 
79 /* DNS header size */
80 #define DNS_HEADER_SIZE		sizeof(struct dns_header)
81 
82 /* DNS request or response header structure */
83 struct dns_header {
84 	uint16_t id;
85 	uint16_t flags;
86 	uint16_t qdcount;
87 	uint16_t ancount;
88 	uint16_t nscount;
89 	uint16_t arcount;
90 } __attribute__ ((packed));
91 
92 /* short structure to describe a DNS question */
93 /* NOTE: big endian structure */
94 struct dns_question {
95 	unsigned short	qtype;		/* question type */
96 	unsigned short	qclass;		/* query class */
97 };
98 
99 /* NOTE: big endian structure */
100 struct dns_query_item {
101 	struct list list;
102 	char name[DNS_MAX_NAME_SIZE];		/* query name */
103 	unsigned short type;			/* question type */
104 	unsigned short class;			/* query class */
105 };
106 
107 /* NOTE: big endian structure */
108 struct dns_answer_item {
109 	struct list list;
110 	char *name;				/* answer name
111 						 * For SRV type, name also includes service
112 						 * and protocol value */
113 	int16_t type;				/* question type */
114 	int16_t class;				/* query class */
115 	int32_t ttl;				/* response TTL */
116 	int16_t priority;			/* SRV type priority */
117 	int16_t weight;				/* SRV type weight */
118 	int16_t port;				/* SRV type port */
119 	uint16_t data_len;			/* number of bytes in target below */
120 	struct sockaddr address;		/* IPv4 or IPv6, network format */
121 	char *target;				/* Response data: SRV or CNAME type target */
122 };
123 
124 struct dns_response_packet {
125 	struct dns_header header;
126 	struct list query_list;
127 	struct list answer_list;
128 	/* authority and additional_information ignored for now */
129 };
130 
131 /*
132  * resolvers section and parameters. It is linked to the name servers
133  * servers points to it.
134  * current resolution are stored in a FIFO list.
135  */
136 struct dns_resolvers {
137 	struct list list;		/* resolvers list */
138 	char *id;			/* resolvers unique identifier */
139 	struct {
140 		const char *file;	/* file where the section appears */
141 		int line;		/* line where the section appears */
142 	} conf;				/* config information */
143 	struct list nameserver_list;	/* dns server list */
144 	int count_nameservers;			/* total number of nameservers in a resolvers section */
145 	int resolve_retries;		/* number of retries before giving up */
146 	struct {			/* time to: */
147 		int retry;		/*   wait for a response before retrying */
148 	} timeout;
149 	struct {			/* time to hold current data when */
150 		int valid;		/*   a response is valid */
151 		int nx;                 /*   a response doesn't exist */
152 		int timeout;            /*   no answer was delivered */
153 		int refused;            /*   dns server refused to answer */
154 		int other;              /*   other dns response errors */
155 	} hold;
156 	struct task *t;			/* timeout management */
157 	struct list curr_resolution;	/* current running resolutions */
158 	struct eb_root query_ids;	/* tree to quickly lookup/retrieve query ids currently in use */
159 					/* used by each nameserver, but stored in resolvers since there must */
160 					/* be a unique relation between an eb_root and an eb_node (resolution) */
161 };
162 
163 /*
164  * structure describing a name server used during name resolution.
165  * A name server belongs to a resolvers section.
166  */
167 struct dns_nameserver {
168 	struct list list;		/* nameserver chained list */
169 	char *id;			/* nameserver unique identifier */
170 	struct {
171 		const char *file;	/* file where the section appears */
172 		int line;		/* line where the section appears */
173 	} conf;				/* config information */
174 	struct dns_resolvers *resolvers;
175 	struct dgram_conn *dgram;		/* transport layer */
176 	struct sockaddr_storage addr;	/* IP address */
177 	struct {			/* numbers relted to this name server: */
178 		long int sent;		/* - queries sent */
179 		long int valid;		/* - valid response */
180 		long int update;	/* - valid response used to update server's IP */
181 		long int cname;		/* - CNAME response requiring new resolution */
182 		long int cname_error;	/* - error when resolving CNAMEs */
183 		long int any_err;	/* - void response (usually because ANY qtype) */
184 		long int nx;		/* - NX response */
185 		long int timeout;	/* - queries which reached timeout */
186 		long int refused;	/* - queries refused */
187 		long int other;		/* - other type of response */
188 		long int invalid;	/* - malformed DNS response */
189 		long int too_big;	/* - too big response */
190 		long int outdated;	/* - outdated response (server slower than the other ones) */
191 		long int truncated;	/* - truncated response */
192 	} counters;
193 };
194 
195 struct dns_options {
196 	int family_prio;	/* which IP family should the resolver use when both are returned */
197 	struct {
198 		int family;
199 		union {
200 			struct in_addr in4;
201 			struct in6_addr in6;
202 		} addr;
203 		union {
204 			struct in_addr in4;
205 			struct in6_addr in6;
206 		} mask;
207 	} pref_net[SRV_MAX_PREF_NET];
208 	int pref_net_nb;               /* The number of registered prefered networks. */
209 };
210 
211 /*
212  * resolution structure associated to single server and used to manage name resolution for
213  * this server.
214  * The only link between the resolution and a nameserver is through the query_id.
215  */
216 struct dns_resolution {
217 	struct list list;		/* resolution list */
218 	struct dns_resolvers *resolvers;	/* resolvers section associated to this resolution */
219 	void *requester;		/* owner of this name resolution */
220 	int (*requester_cb)(struct dns_resolution *, struct dns_nameserver *, struct dns_response_packet *);
221 					/* requester callback for valid response */
222 	int (*requester_error_cb)(struct dns_resolution *, int);
223 					/* requester callback, for error management */
224 	char *hostname_dn;		/* server hostname in domain name label format */
225 	int hostname_dn_len;		/* server domain name label len */
226 	struct dns_options *opts;       /* IP selection options inherited from the configuration file. */
227 	unsigned int last_resolution;	/* time of the lastest valid resolution */
228 	unsigned int last_sent_packet;	/* time of the latest DNS packet sent */
229 	unsigned int last_status_change;	/* time of the latest DNS resolution status change */
230 	int query_id;			/* DNS query ID dedicated for this resolution */
231 	struct eb32_node qid;		/* ebtree query id */
232 	int query_type;
233 		/* query type to send. By default DNS_RTYPE_A or DNS_RTYPE_AAAA depending on resolver_family_priority */
234 	int status;			/* status of the resolution being processed RSLV_STATUS_* */
235 	int step;			/* */
236 	int try;			/* current resolution try */
237 	int try_cname;			/* number of CNAME requests sent */
238 	int nb_responses;		/* count number of responses received */
239 };
240 
241 /* last resolution status code */
242 enum {
243 	RSLV_STATUS_NONE	= 0,	/* no resolution occured yet */
244 	RSLV_STATUS_VALID,		/* no error */
245 	RSLV_STATUS_INVALID,		/* invalid responses */
246 	RSLV_STATUS_ERROR,		/* error */
247 	RSLV_STATUS_NX,			/* NXDOMAIN */
248 	RSLV_STATUS_REFUSED,		/* server refused our query */
249 	RSLV_STATUS_TIMEOUT,		/* no response from DNS servers */
250 	RSLV_STATUS_OTHER,		/* other errors */
251 };
252 
253 /* current resolution step */
254 enum {
255 	RSLV_STEP_NONE		= 0,	/* nothing happening currently */
256 	RSLV_STEP_RUNNING,		/* resolution is running */
257 };
258 
259 /* return codes after analyzing a DNS response */
260 enum {
261 	DNS_RESP_VALID		= 0,	/* valid response */
262 	DNS_RESP_INVALID,		/* invalid response (various type of errors can trigger it) */
263 	DNS_RESP_ERROR,			/* DNS error code */
264 	DNS_RESP_NX_DOMAIN,		/* resolution unsuccessful */
265 	DNS_RESP_REFUSED,		/* DNS server refused to answer */
266 	DNS_RESP_ANCOUNT_ZERO,		/* no answers in the response */
267 	DNS_RESP_WRONG_NAME,		/* response does not match query name */
268 	DNS_RESP_CNAME_ERROR,		/* error when resolving a CNAME in an atomic response */
269 	DNS_RESP_TIMEOUT,		/* DNS server has not answered in time */
270 	DNS_RESP_TRUNCATED,		/* DNS response is truncated */
271 	DNS_RESP_NO_EXPECTED_RECORD,	/* No expected records were found in the response */
272 	DNS_RESP_QUERY_COUNT_ERROR,	/* we did not get the expected number of queries in the response */
273 };
274 
275 /* return codes after searching an IP in a DNS response buffer, using a family preference */
276 enum {
277 	DNS_UPD_NO 		= 1,	/* provided IP was found and preference is matched
278 					 * OR provided IP found and preference is not matched, but no IP
279 					 *    matching preference was found */
280 	DNS_UPD_SRVIP_NOT_FOUND,	/* provided IP not found
281 					 * OR provided IP found and preference is not match and an IP
282 					 *    matching preference was found */
283 	DNS_UPD_CNAME,			/* CNAME without any IP provided in the response */
284 	DNS_UPD_NAME_ERROR,		/* name in the response did not match the query */
285 	DNS_UPD_NO_IP_FOUND,		/* no IP could be found in the response */
286 };
287 
288 #endif /* _TYPES_DNS_H */
289