1 /*
2  * Copyright 2005 Niels Provos <provos@citi.umich.edu>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Niels Provos.
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /*
32  * ++Copyright++ 1983, 1989, 1993
33  * -
34  * Copyright (c) 1983, 1989, 1993
35  *    The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. Neither the name of the University nor the names of its contributors
46  *    may be used to endorse or promote products derived from this software
47  *    without specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  * -
61  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
62  *
63  * Permission to use, copy, modify, and distribute this software for any
64  * purpose with or without fee is hereby granted, provided that the above
65  * copyright notice and this permission notice appear in all copies, and that
66  * the name of Digital Equipment Corporation not be used in advertising or
67  * publicity pertaining to distribution of the document or software without
68  * specific, written prior permission.
69  *
70  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
71  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
72  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
73  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
74  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
75  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
76  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
77  * SOFTWARE.
78  * -
79  * Portions Copyright (c) 1995 by International Business Machines, Inc.
80  *
81  * International Business Machines, Inc. (hereinafter called IBM) grants
82  * permission under its copyrights to use, copy, modify, and distribute this
83  * Software with or without fee, provided that the above copyright notice and
84  * all paragraphs of this notice appear in all copies, and that the name of IBM
85  * not be used in connection with the marketing of any product incorporating
86  * the Software or modifications thereof, without specific, written prior
87  * permission.
88  *
89  * To the extent it has a right to do so, IBM grants an immunity from suit
90  * under its patents, if any, for the use, sale or manufacture of products to
91  * the extent that such products are used for performing Domain Name System
92  * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
93  * granted for any product per se or for any other function of any product.
94  *
95  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
96  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
97  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
98  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
99  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
100  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
101  * --Copyright--
102  */
103 
104 #ifndef _DNSRES_INTERNAL_H_
105 #define _DNSRES_INTERNAL_H_
106 
107 /*
108  * Define constants based on rfc883
109  */
110 #define DNSRES_PACKETSZ		512	/* maximum packet size */
111 #define DNSRES_MAXDNAME		1025	/* maximum presentation domain name */
112 #define DNSRES_MAXCDNAME	255	/* maximum compressed domain name */
113 #define DNSRES_MAXLABEL		63	/* maximum length of domain label */
114 #define DNSRES_HFIXEDSZ		12	/* #/bytes of fixed data in header */
115 #define DNSRES_QFIXEDSZ		4	/* #/bytes of fixed data in query */
116 #define DNSRES_RRFIXEDSZ	10	/* #/bytes of fixed data in r record */
117 #define DNSRES_INT32SZ		4	/* for systems without 32-bit ints */
118 #define DNSRES_INT16SZ		2	/* for systems without 16-bit ints */
119 #define DNSRES_INADDRSZ		4	/* IPv4 T_A */
120 #define DNSRES_IN6ADDRSZ	16	/* IPv6 T_AAAA */
121 
122 #define	MAXPACKET	(64*1024)
123 
124 /*
125  * Structure for query header.  The order of the fields is machine- and
126  * compiler-dependent, depending on the byte/bit order and the layout
127  * of bit fields.  We use bit fields only in int variables, as this
128  * is all ANSI requires.  This requires a somewhat confusing rearrangement.
129  */
130 
131 typedef struct {
132 	unsigned	id :16;		/* query identification number */
133 #ifdef HAVE_BIG_ENDIAN
134 			/* fields in third byte */
135 	unsigned	qr: 1;		/* response flag */
136 	unsigned	opcode: 4;	/* purpose of message */
137 	unsigned	aa: 1;		/* authoritive answer */
138 	unsigned	tc: 1;		/* truncated message */
139 	unsigned	rd: 1;		/* recursion desired */
140 			/* fields in fourth byte */
141 	unsigned	ra: 1;		/* recursion available */
142 	unsigned	unused :1;	/* unused bits (MBZ as of 4.9.3a3) */
143 	unsigned	ad: 1;		/* authentic data from named */
144 	unsigned	cd: 1;		/* checking disabled by resolver */
145 	unsigned	rcode :4;	/* response code */
146 #else /* !HAVE_BIG_ENDIAN - for our little endians */
147 			/* fields in third byte */
148 	unsigned	rd :1;		/* recursion desired */
149 	unsigned	tc :1;		/* truncated message */
150 	unsigned	aa :1;		/* authoritive answer */
151 	unsigned	opcode :4;	/* purpose of message */
152 	unsigned	qr :1;		/* response flag */
153 			/* fields in fourth byte */
154 	unsigned	rcode :4;	/* response code */
155 	unsigned	cd: 1;		/* checking disabled by resolver */
156 	unsigned	ad: 1;		/* authentic data from named */
157 	unsigned	unused :1;	/* unused bits (MBZ as of 4.9.3a3) */
158 	unsigned	ra :1;		/* recursion available */
159 #endif
160 			/* remaining bytes */
161 	unsigned	qdcount :16;	/* number of question entries */
162 	unsigned	ancount :16;	/* number of answer entries */
163 	unsigned	nscount :16;	/* number of authority entries */
164 	unsigned	arcount :16;	/* number of resource entries */
165 } DNSRES_HEADER;
166 
167 typedef union {
168 	DNSRES_HEADER hdr;
169 	u_char buf[MAXPACKET];
170 } querybuf;
171 
172 struct dnsres_socket {
173 	struct event ev;
174 	struct sockaddr *nsap;
175 	socklen_t salen;
176 
177 	int s;		/* socket used for communications */
178 	int connected;	/* is the socket connected */
179 	int vc;		/* is the socket a virtual ciruit? */
180 	int af;		/* address family of socket */
181 };
182 
183 struct dnsres_target {
184 	struct dnsres_target *next;
185 	const char *name;	/* domain name */
186 	int qclass, qtype;	/* class and type of query */
187 	u_char *answer;		/* buffer to put answer */
188 	int anslen;		/* size of answer buffer */
189 	int n;			/* result length */
190 };
191 
192 #define MULTI_PTRS_ARE_ALIASES 1	/* XXX - experimental */
193 
194 #define	MAXALIASES	35
195 #define	MAXADDRS	35
196 
197 /* state used by all the gethostby* functions */
198 
199 struct dnsres_cbstate {
200 	void (*cb)(struct dnsres_hostent *hp, int dr_errno, void *arg);
201 	void *cb_arg;
202 
203 	struct dnsres_hostent *hp;
204 	char *name;		/* the name we are trying to resolve */
205 	size_t name_len;
206 
207 	int af;
208 	struct dnsres *_resp;
209 
210 	char lookups[MAXDNSLUS];
211 	int lookup_index;
212 	struct dnsres_target q;
213 	int size;
214 	querybuf *buf;
215 	char qbuf[MAXDNAME+1];
216 
217 	void (*internal_cb)(struct dnsres_hostent *, struct dnsres_cbstate *);
218 
219 	/* More resolver state to carry around */
220 	char *h_addr_ptrs[MAXADDRS + 1];
221 
222 	struct dnsres_hostent host;
223 	char *host_aliases[MAXALIASES];
224 	char hostbuf[BUFSIZ+1];
225 	union {
226 		struct in_addr _host_in_addr;
227 		u_char _host_addr[16];		/* IPv4 or IPv6 */
228 	} _host_addr_u;
229 #define host_addr _host_addr_u._host_addr
230 };
231 
232 /* state used by all the res functions */
233 
234 #if PACKETSZ > 1024
235 #define UDP_MAXPACKET	PACKETSZ
236 #else
237 #define UDP_MAXPACKET	1024
238 #endif
239 
240 struct res_search_state {
241 	struct dnsres *_resp;
242 
243 	const char *name;
244 	struct dnsres_target *target;
245 	int ancount;	/* used when we have multiple queries */
246 
247 	void (*cb)(int, void *);
248 	void *cb_arg;
249 
250 	void (*res_conditional_cb)(struct res_search_state *);
251 
252 	int trailing_dot;
253 	u_int dots;
254 	int tried_as_is;
255 	int saved_herrno;
256 	int dont_save_errno;
257 	int done;
258 	int got_nodata;
259 	int got_servfail;
260 
261 	const char * const *domain;
262 
263 	/* res_query state */
264 	u_char buf[UDP_MAXPACKET];
265 
266 	/* res_send state */
267 	struct dnsres_socket ds;		/* XXX - move away */
268 
269 	void (*send_cb)(int, struct res_search_state *);
270 	const u_char *send_buf;
271 	int resplen;
272 	int send_buflen;
273 	int gotsomewhere;
274 	int terrno;
275 	int v_circuit;
276 	int try;
277 	int connreset;
278 	u_int badns;	/* XXX NSMAX can't exceed #/bits in this var */
279 	int ns;
280 	int ret;
281 
282 	int read_len;	/* used by res_send_vcircuit magic */
283 	int truncated;
284 	u_char *cp;
285 };
286 
287 /*
288  * Encapsulates the query state, so that it can be passed around between
289  * functions.
290  */
291 struct dnsres_cbstate *dnsres_cbstate_new(
292 	struct dnsres *_resp, const char *name, size_t len,
293         void (*cb)(struct dnsres_hostent *, int, void *), void *arg);
294 
295 /*
296  * Defines for handling compressed domain names
297  */
298 #define DNSRES_INDIR_MASK	0xc0
299 
300 /*
301  * Inline versions of get/put short/long.  Pointer is advanced.
302  *
303  * These macros demonstrate the property of C whereby it can be
304  * portable or it can be elegant but rarely both.
305  */
306 #define DNSRES_GETSHORT(s, cp) { \
307 	unsigned char *t_cp = (unsigned char *)(cp); \
308 	(s) = ((u_int16_t)t_cp[0] << 8) \
309 	    | ((u_int16_t)t_cp[1]) \
310 	    ; \
311 	(cp) += INT16SZ; \
312 }
313 
314 #define DNSRES_GETLONG(l, cp) { \
315 	unsigned char *t_cp = (unsigned char *)(cp); \
316 	(l) = ((u_int32_t)t_cp[0] << 24) \
317 	    | ((u_int32_t)t_cp[1] << 16) \
318 	    | ((u_int32_t)t_cp[2] << 8) \
319 	    | ((u_int32_t)t_cp[3]) \
320 	    ; \
321 	(cp) += INT32SZ; \
322 }
323 
324 #define DNSRES_PUTSHORT(s, cp) { \
325 	u_int16_t t_s = (u_int16_t)(s); \
326 	unsigned char *t_cp = (unsigned char *)(cp); \
327 	*t_cp++ = t_s >> 8; \
328 	*t_cp   = t_s; \
329 	(cp) += INT16SZ; \
330 }
331 
332 #define DNSRES_PUTLONG(l, cp) { \
333 	u_int32_t t_l = (u_int32_t)(l); \
334 	unsigned char *t_cp = (unsigned char *)(cp); \
335 	*t_cp++ = t_l >> 24; \
336 	*t_cp++ = t_l >> 16; \
337 	*t_cp++ = t_l >> 8; \
338 	*t_cp   = t_l; \
339 	(cp) += INT32SZ; \
340 }
341 
342 #endif /* _DNSRES_INTERNAL_H_ */
343