xref: /freebsd/lib/libc/resolv/res_findzonecut.c (revision dc36d6f9)
1f62c4786SHajimu UMEMOTO 
26e778a7eSPedro F. Giffuni /*-
36e778a7eSPedro F. Giffuni  * SPDX-License-Identifier: ISC
46e778a7eSPedro F. Giffuni  *
5f62c4786SHajimu UMEMOTO  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
6f62c4786SHajimu UMEMOTO  * Copyright (c) 1999 by Internet Software Consortium.
7f62c4786SHajimu UMEMOTO  *
8f62c4786SHajimu UMEMOTO  * Permission to use, copy, modify, and distribute this software for any
9f62c4786SHajimu UMEMOTO  * purpose with or without fee is hereby granted, provided that the above
10f62c4786SHajimu UMEMOTO  * copyright notice and this permission notice appear in all copies.
11f62c4786SHajimu UMEMOTO  *
12f62c4786SHajimu UMEMOTO  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
13f62c4786SHajimu UMEMOTO  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14f62c4786SHajimu UMEMOTO  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
15f62c4786SHajimu UMEMOTO  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16f62c4786SHajimu UMEMOTO  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17f62c4786SHajimu UMEMOTO  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18f62c4786SHajimu UMEMOTO  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19f62c4786SHajimu UMEMOTO  */
20f62c4786SHajimu UMEMOTO 
21f62c4786SHajimu UMEMOTO /* Import. */
22f62c4786SHajimu UMEMOTO 
23f62c4786SHajimu UMEMOTO #include "port_before.h"
24f62c4786SHajimu UMEMOTO 
25f62c4786SHajimu UMEMOTO #include <sys/param.h>
26f62c4786SHajimu UMEMOTO #include <sys/socket.h>
27f62c4786SHajimu UMEMOTO #include <sys/time.h>
28f62c4786SHajimu UMEMOTO 
29f62c4786SHajimu UMEMOTO #include <netinet/in.h>
30f62c4786SHajimu UMEMOTO #include <arpa/inet.h>
31f62c4786SHajimu UMEMOTO #include <arpa/nameser.h>
32f62c4786SHajimu UMEMOTO 
33f62c4786SHajimu UMEMOTO #include <errno.h>
34f62c4786SHajimu UMEMOTO #include <limits.h>
35f62c4786SHajimu UMEMOTO #include <netdb.h>
36f62c4786SHajimu UMEMOTO #include <stdarg.h>
37f62c4786SHajimu UMEMOTO #include <stdio.h>
38f62c4786SHajimu UMEMOTO #include <stdlib.h>
39f62c4786SHajimu UMEMOTO #include <string.h>
40f62c4786SHajimu UMEMOTO 
41f62c4786SHajimu UMEMOTO #include <isc/list.h>
42f62c4786SHajimu UMEMOTO 
43f62c4786SHajimu UMEMOTO #include "port_after.h"
44f62c4786SHajimu UMEMOTO 
45f62c4786SHajimu UMEMOTO #include <resolv.h>
46f62c4786SHajimu UMEMOTO 
47f62c4786SHajimu UMEMOTO /* Data structures. */
48f62c4786SHajimu UMEMOTO 
49f62c4786SHajimu UMEMOTO typedef struct rr_a {
50f62c4786SHajimu UMEMOTO 	LINK(struct rr_a)	link;
51f62c4786SHajimu UMEMOTO 	union res_sockaddr_union addr;
52f62c4786SHajimu UMEMOTO } rr_a;
53f62c4786SHajimu UMEMOTO typedef LIST(rr_a) rrset_a;
54f62c4786SHajimu UMEMOTO 
55f62c4786SHajimu UMEMOTO typedef struct rr_ns {
56f62c4786SHajimu UMEMOTO 	LINK(struct rr_ns)	link;
57f62c4786SHajimu UMEMOTO 	const char *		name;
58f62c4786SHajimu UMEMOTO 	unsigned int		flags;
59f62c4786SHajimu UMEMOTO 	rrset_a			addrs;
60f62c4786SHajimu UMEMOTO } rr_ns;
61f62c4786SHajimu UMEMOTO typedef LIST(rr_ns) rrset_ns;
62f62c4786SHajimu UMEMOTO 
63f62c4786SHajimu UMEMOTO #define	RR_NS_HAVE_V4		0x01
64f62c4786SHajimu UMEMOTO #define	RR_NS_HAVE_V6		0x02
65f62c4786SHajimu UMEMOTO 
66f62c4786SHajimu UMEMOTO /* Forward. */
67f62c4786SHajimu UMEMOTO 
68f62c4786SHajimu UMEMOTO static int	satisfy(res_state, const char *, rrset_ns *,
69f62c4786SHajimu UMEMOTO 			union res_sockaddr_union *, int);
70f62c4786SHajimu UMEMOTO static int	add_addrs(res_state, rr_ns *,
71f62c4786SHajimu UMEMOTO 			  union res_sockaddr_union *, int);
72f62c4786SHajimu UMEMOTO static int	get_soa(res_state, const char *, ns_class, int,
73f62c4786SHajimu UMEMOTO 			char *, size_t, char *, size_t,
74f62c4786SHajimu UMEMOTO 			rrset_ns *);
75f62c4786SHajimu UMEMOTO static int	get_ns(res_state, const char *, ns_class, int, rrset_ns *);
76f62c4786SHajimu UMEMOTO static int	get_glue(res_state, ns_class, int, rrset_ns *);
77f62c4786SHajimu UMEMOTO static int	save_ns(res_state, ns_msg *, ns_sect,
78f62c4786SHajimu UMEMOTO 			const char *, ns_class, int, rrset_ns *);
79f62c4786SHajimu UMEMOTO static int	save_a(res_state, ns_msg *, ns_sect,
80f62c4786SHajimu UMEMOTO 		       const char *, ns_class, int, rr_ns *);
81f62c4786SHajimu UMEMOTO static void	free_nsrrset(rrset_ns *);
82f62c4786SHajimu UMEMOTO static void	free_nsrr(rrset_ns *, rr_ns *);
83f62c4786SHajimu UMEMOTO static rr_ns *	find_ns(rrset_ns *, const char *);
84f62c4786SHajimu UMEMOTO static int	do_query(res_state, const char *, ns_class, ns_type,
85f62c4786SHajimu UMEMOTO 			 u_char *, ns_msg *);
86f62c4786SHajimu UMEMOTO static void	res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2);
87f62c4786SHajimu UMEMOTO 
88f62c4786SHajimu UMEMOTO /* Macros. */
89f62c4786SHajimu UMEMOTO 
90f62c4786SHajimu UMEMOTO #define DPRINTF(x) do {\
91f62c4786SHajimu UMEMOTO 		int save_errno = errno; \
92f62c4786SHajimu UMEMOTO 		if ((statp->options & RES_DEBUG) != 0U) res_dprintf x; \
93f62c4786SHajimu UMEMOTO 		errno = save_errno; \
94f62c4786SHajimu UMEMOTO 	} while (0)
95f62c4786SHajimu UMEMOTO 
96f62c4786SHajimu UMEMOTO /* Public. */
97f62c4786SHajimu UMEMOTO 
98dde4a85dSHajimu UMEMOTO /*%
99f62c4786SHajimu UMEMOTO  *	find enclosing zone for a <dname,class>, and some server addresses
100dde4a85dSHajimu UMEMOTO  *
101f62c4786SHajimu UMEMOTO  * parameters:
102dde4a85dSHajimu UMEMOTO  *\li	res - resolver context to work within (is modified)
103dde4a85dSHajimu UMEMOTO  *\li	dname - domain name whose enclosing zone is desired
104dde4a85dSHajimu UMEMOTO  *\li	class - class of dname (and its enclosing zone)
105dde4a85dSHajimu UMEMOTO  *\li	zname - found zone name
106dde4a85dSHajimu UMEMOTO  *\li	zsize - allocated size of zname
107dde4a85dSHajimu UMEMOTO  *\li	addrs - found server addresses
108dde4a85dSHajimu UMEMOTO  *\li	naddrs - max number of addrs
109dde4a85dSHajimu UMEMOTO  *
110f62c4786SHajimu UMEMOTO  * return values:
111dde4a85dSHajimu UMEMOTO  *\li	< 0 - an error occurred (check errno)
112dde4a85dSHajimu UMEMOTO  *\li	= 0 - zname is now valid, but addrs[] wasn't changed
113dde4a85dSHajimu UMEMOTO  *\li	> 0 - zname is now valid, and return value is number of addrs[] found
114dde4a85dSHajimu UMEMOTO  *
115f62c4786SHajimu UMEMOTO  * notes:
116dde4a85dSHajimu UMEMOTO  *\li	this function calls res_nsend() which means it depends on correctly
117f62c4786SHajimu UMEMOTO  *	functioning recursive nameservers (usually defined in /etc/resolv.conf
11832223c1bSPedro F. Giffuni  *	or its local equivalent).
119f62c4786SHajimu UMEMOTO  *
120dde4a85dSHajimu UMEMOTO  *\li	we start by asking for an SOA<dname,class>.  if we get one as an
121f62c4786SHajimu UMEMOTO  *	answer, that just means <dname,class> is a zone top, which is fine.
122f62c4786SHajimu UMEMOTO  *	more than likely we'll be told to go pound sand, in the form of a
123f62c4786SHajimu UMEMOTO  *	negative answer.
124f62c4786SHajimu UMEMOTO  *
125dde4a85dSHajimu UMEMOTO  *\li	note that we are not prepared to deal with referrals since that would
126f62c4786SHajimu UMEMOTO  *	only come from authority servers and our correctly functioning local
127f62c4786SHajimu UMEMOTO  *	recursive server would have followed the referral and got us something
128f62c4786SHajimu UMEMOTO  *	more definite.
129f62c4786SHajimu UMEMOTO  *
130dde4a85dSHajimu UMEMOTO  *\li	if the authority section contains an SOA, this SOA should also be the
131f62c4786SHajimu UMEMOTO  *	closest enclosing zone, since any intermediary zone cuts would've been
132f62c4786SHajimu UMEMOTO  *	returned as referrals and dealt with by our correctly functioning local
133f62c4786SHajimu UMEMOTO  *	recursive name server.  but an SOA in the authority section should NOT
134f62c4786SHajimu UMEMOTO  *	match our dname (since that would have been returned in the answer
135f62c4786SHajimu UMEMOTO  *	section).  an authority section SOA has to be "above" our dname.
136f62c4786SHajimu UMEMOTO  *
137dde4a85dSHajimu UMEMOTO  *\li	however, since authority section SOA's were once optional, it's
138f62c4786SHajimu UMEMOTO  *	possible that we'll have to go hunting for the enclosing SOA by
139f62c4786SHajimu UMEMOTO  *	ripping labels off the front of our dname -- this is known as "doing
140f62c4786SHajimu UMEMOTO  *	it the hard way."
141f62c4786SHajimu UMEMOTO  *
142dde4a85dSHajimu UMEMOTO  *\li	ultimately we want some server addresses, which are ideally the ones
143f62c4786SHajimu UMEMOTO  *	pertaining to the SOA.MNAME, but only if there is a matching NS RR.
144f62c4786SHajimu UMEMOTO  *	so the second phase (after we find an SOA) is to go looking for the
145f62c4786SHajimu UMEMOTO  *	NS RRset for that SOA's zone.
146f62c4786SHajimu UMEMOTO  *
147dde4a85dSHajimu UMEMOTO  *\li	no answer section processed by this code is allowed to contain CNAME
148f62c4786SHajimu UMEMOTO  *	or DNAME RR's.  for the SOA query this means we strip a label and
149f62c4786SHajimu UMEMOTO  *	keep going.  for the NS and A queries this means we just give up.
150f62c4786SHajimu UMEMOTO  */
151f62c4786SHajimu UMEMOTO 
152d808369aSHajimu UMEMOTO #ifndef _LIBC
153f62c4786SHajimu UMEMOTO int
res_findzonecut(res_state statp,const char * dname,ns_class class,int opts,char * zname,size_t zsize,struct in_addr * addrs,int naddrs)154f62c4786SHajimu UMEMOTO res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
155f62c4786SHajimu UMEMOTO 		char *zname, size_t zsize, struct in_addr *addrs, int naddrs)
156f62c4786SHajimu UMEMOTO {
157f62c4786SHajimu UMEMOTO 	int result, i;
158f62c4786SHajimu UMEMOTO 	union res_sockaddr_union *u;
159f62c4786SHajimu UMEMOTO 
160f62c4786SHajimu UMEMOTO 
161f62c4786SHajimu UMEMOTO 	opts |= RES_IPV4ONLY;
162f62c4786SHajimu UMEMOTO 	opts &= ~RES_IPV6ONLY;
163f62c4786SHajimu UMEMOTO 
164f62c4786SHajimu UMEMOTO 	u = calloc(naddrs, sizeof(*u));
165f62c4786SHajimu UMEMOTO 	if (u == NULL)
166f62c4786SHajimu UMEMOTO 		return(-1);
167f62c4786SHajimu UMEMOTO 
168f62c4786SHajimu UMEMOTO 	result = res_findzonecut2(statp, dname, class, opts, zname, zsize,
169f62c4786SHajimu UMEMOTO 				  u, naddrs);
170f62c4786SHajimu UMEMOTO 
171f62c4786SHajimu UMEMOTO 	for (i = 0; i < result; i++) {
172f62c4786SHajimu UMEMOTO 		addrs[i] = u[i].sin.sin_addr;
173f62c4786SHajimu UMEMOTO 	}
174f62c4786SHajimu UMEMOTO 	free(u);
175f62c4786SHajimu UMEMOTO 	return (result);
176f62c4786SHajimu UMEMOTO }
177d808369aSHajimu UMEMOTO #endif
178f62c4786SHajimu UMEMOTO 
179f62c4786SHajimu UMEMOTO int
res_findzonecut2(res_state statp,const char * dname,ns_class class,int opts,char * zname,size_t zsize,union res_sockaddr_union * addrs,int naddrs)180f62c4786SHajimu UMEMOTO res_findzonecut2(res_state statp, const char *dname, ns_class class, int opts,
181f62c4786SHajimu UMEMOTO 		 char *zname, size_t zsize, union res_sockaddr_union *addrs,
182f62c4786SHajimu UMEMOTO 		 int naddrs)
183f62c4786SHajimu UMEMOTO {
184f62c4786SHajimu UMEMOTO 	char mname[NS_MAXDNAME];
185f62c4786SHajimu UMEMOTO 	u_long save_pfcode;
186f62c4786SHajimu UMEMOTO 	rrset_ns nsrrs;
187f62c4786SHajimu UMEMOTO 	int n;
188f62c4786SHajimu UMEMOTO 
189f62c4786SHajimu UMEMOTO 	DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d",
190f62c4786SHajimu UMEMOTO 		 dname, p_class(class), (long)zsize, naddrs));
191f62c4786SHajimu UMEMOTO 	save_pfcode = statp->pfcode;
192f62c4786SHajimu UMEMOTO 	statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX |
193f62c4786SHajimu UMEMOTO 			 RES_PRF_QUES | RES_PRF_ANS |
194f62c4786SHajimu UMEMOTO 			 RES_PRF_AUTH | RES_PRF_ADD;
195f62c4786SHajimu UMEMOTO 	INIT_LIST(nsrrs);
196f62c4786SHajimu UMEMOTO 
197f62c4786SHajimu UMEMOTO 	DPRINTF(("get the soa, and see if it has enough glue"));
198f62c4786SHajimu UMEMOTO 	if ((n = get_soa(statp, dname, class, opts, zname, zsize,
199f62c4786SHajimu UMEMOTO 			 mname, sizeof mname, &nsrrs)) < 0 ||
200f62c4786SHajimu UMEMOTO 	    ((opts & RES_EXHAUSTIVE) == 0 &&
201f62c4786SHajimu UMEMOTO 	     (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
202f62c4786SHajimu UMEMOTO 		goto done;
203f62c4786SHajimu UMEMOTO 
204f62c4786SHajimu UMEMOTO 	DPRINTF(("get the ns rrset and see if it has enough glue"));
205f62c4786SHajimu UMEMOTO 	if ((n = get_ns(statp, zname, class, opts, &nsrrs)) < 0 ||
206f62c4786SHajimu UMEMOTO 	    ((opts & RES_EXHAUSTIVE) == 0 &&
207f62c4786SHajimu UMEMOTO 	     (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
208f62c4786SHajimu UMEMOTO 		goto done;
209f62c4786SHajimu UMEMOTO 
210f62c4786SHajimu UMEMOTO 	DPRINTF(("get the missing glue and see if it's finally enough"));
211f62c4786SHajimu UMEMOTO 	if ((n = get_glue(statp, class, opts, &nsrrs)) >= 0)
212f62c4786SHajimu UMEMOTO 		n = satisfy(statp, mname, &nsrrs, addrs, naddrs);
213f62c4786SHajimu UMEMOTO 
214f62c4786SHajimu UMEMOTO  done:
215f62c4786SHajimu UMEMOTO 	DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK"));
216f62c4786SHajimu UMEMOTO 	free_nsrrset(&nsrrs);
217f62c4786SHajimu UMEMOTO 	statp->pfcode = save_pfcode;
218f62c4786SHajimu UMEMOTO 	return (n);
219f62c4786SHajimu UMEMOTO }
220f62c4786SHajimu UMEMOTO 
221f62c4786SHajimu UMEMOTO /* Private. */
222f62c4786SHajimu UMEMOTO 
223f62c4786SHajimu UMEMOTO static int
satisfy(res_state statp,const char * mname,rrset_ns * nsrrsp,union res_sockaddr_union * addrs,int naddrs)224f62c4786SHajimu UMEMOTO satisfy(res_state statp, const char *mname, rrset_ns *nsrrsp,
225f62c4786SHajimu UMEMOTO 	union res_sockaddr_union *addrs, int naddrs)
226f62c4786SHajimu UMEMOTO {
227f62c4786SHajimu UMEMOTO 	rr_ns *nsrr;
228f62c4786SHajimu UMEMOTO 	int n, x;
229f62c4786SHajimu UMEMOTO 
230f62c4786SHajimu UMEMOTO 	n = 0;
231f62c4786SHajimu UMEMOTO 	nsrr = find_ns(nsrrsp, mname);
232f62c4786SHajimu UMEMOTO 	if (nsrr != NULL) {
233f62c4786SHajimu UMEMOTO 		x = add_addrs(statp, nsrr, addrs, naddrs);
234f62c4786SHajimu UMEMOTO 		addrs += x;
235f62c4786SHajimu UMEMOTO 		naddrs -= x;
236f62c4786SHajimu UMEMOTO 		n += x;
237f62c4786SHajimu UMEMOTO 	}
238f62c4786SHajimu UMEMOTO 	for (nsrr = HEAD(*nsrrsp);
239f62c4786SHajimu UMEMOTO 	     nsrr != NULL && naddrs > 0;
240f62c4786SHajimu UMEMOTO 	     nsrr = NEXT(nsrr, link))
241f62c4786SHajimu UMEMOTO 		if (ns_samename(nsrr->name, mname) != 1) {
242f62c4786SHajimu UMEMOTO 			x = add_addrs(statp, nsrr, addrs, naddrs);
243f62c4786SHajimu UMEMOTO 			addrs += x;
244f62c4786SHajimu UMEMOTO 			naddrs -= x;
245f62c4786SHajimu UMEMOTO 			n += x;
246f62c4786SHajimu UMEMOTO 		}
247f62c4786SHajimu UMEMOTO 	DPRINTF(("satisfy(%s): %d", mname, n));
248f62c4786SHajimu UMEMOTO 	return (n);
249f62c4786SHajimu UMEMOTO }
250f62c4786SHajimu UMEMOTO 
251f62c4786SHajimu UMEMOTO static int
add_addrs(res_state statp,rr_ns * nsrr,union res_sockaddr_union * addrs,int naddrs)252f62c4786SHajimu UMEMOTO add_addrs(res_state statp, rr_ns *nsrr,
253f62c4786SHajimu UMEMOTO 	  union res_sockaddr_union *addrs, int naddrs)
254f62c4786SHajimu UMEMOTO {
255f62c4786SHajimu UMEMOTO 	rr_a *arr;
256f62c4786SHajimu UMEMOTO 	int n = 0;
257f62c4786SHajimu UMEMOTO 
258f62c4786SHajimu UMEMOTO 	for (arr = HEAD(nsrr->addrs); arr != NULL; arr = NEXT(arr, link)) {
259f62c4786SHajimu UMEMOTO 		if (naddrs <= 0)
260f62c4786SHajimu UMEMOTO 			return (0);
261f62c4786SHajimu UMEMOTO 		*addrs++ = arr->addr;
262f62c4786SHajimu UMEMOTO 		naddrs--;
263f62c4786SHajimu UMEMOTO 		n++;
264f62c4786SHajimu UMEMOTO 	}
265f62c4786SHajimu UMEMOTO 	DPRINTF(("add_addrs: %d", n));
266f62c4786SHajimu UMEMOTO 	return (n);
267f62c4786SHajimu UMEMOTO }
268f62c4786SHajimu UMEMOTO 
269f62c4786SHajimu UMEMOTO static int
get_soa(res_state statp,const char * dname,ns_class class,int opts,char * zname,size_t zsize,char * mname,size_t msize,rrset_ns * nsrrsp)270f62c4786SHajimu UMEMOTO get_soa(res_state statp, const char *dname, ns_class class, int opts,
271f62c4786SHajimu UMEMOTO 	char *zname, size_t zsize, char *mname, size_t msize,
272f62c4786SHajimu UMEMOTO 	rrset_ns *nsrrsp)
273f62c4786SHajimu UMEMOTO {
274f62c4786SHajimu UMEMOTO 	char tname[NS_MAXDNAME];
275f62c4786SHajimu UMEMOTO 	u_char *resp = NULL;
276f62c4786SHajimu UMEMOTO 	int n, i, ancount, nscount;
277f62c4786SHajimu UMEMOTO 	ns_sect sect;
278f62c4786SHajimu UMEMOTO 	ns_msg msg;
279f62c4786SHajimu UMEMOTO 	u_int rcode;
280f62c4786SHajimu UMEMOTO 
281f62c4786SHajimu UMEMOTO 	/*
282f62c4786SHajimu UMEMOTO 	 * Find closest enclosing SOA, even if it's for the root zone.
283f62c4786SHajimu UMEMOTO 	 */
284f62c4786SHajimu UMEMOTO 
285f62c4786SHajimu UMEMOTO 	/* First canonicalize dname (exactly one unescaped trailing "."). */
286f62c4786SHajimu UMEMOTO 	if (ns_makecanon(dname, tname, sizeof tname) < 0)
287f62c4786SHajimu UMEMOTO 		goto cleanup;
288f62c4786SHajimu UMEMOTO 	dname = tname;
289f62c4786SHajimu UMEMOTO 
290f62c4786SHajimu UMEMOTO 	resp = malloc(NS_MAXMSG);
291f62c4786SHajimu UMEMOTO 	if (resp == NULL)
292f62c4786SHajimu UMEMOTO 		goto cleanup;
293f62c4786SHajimu UMEMOTO 
294f62c4786SHajimu UMEMOTO 	/* Now grovel the subdomains, hunting for an SOA answer or auth. */
295f62c4786SHajimu UMEMOTO 	for (;;) {
296f62c4786SHajimu UMEMOTO 		/* Leading or inter-label '.' are skipped here. */
297f62c4786SHajimu UMEMOTO 		while (*dname == '.')
298f62c4786SHajimu UMEMOTO 			dname++;
299f62c4786SHajimu UMEMOTO 
300f62c4786SHajimu UMEMOTO 		/* Is there an SOA? */
301f62c4786SHajimu UMEMOTO 		n = do_query(statp, dname, class, ns_t_soa, resp, &msg);
302f62c4786SHajimu UMEMOTO 		if (n < 0) {
303f62c4786SHajimu UMEMOTO 			DPRINTF(("get_soa: do_query('%s', %s) failed (%d)",
304f62c4786SHajimu UMEMOTO 				 dname, p_class(class), n));
305f62c4786SHajimu UMEMOTO 			goto cleanup;
306f62c4786SHajimu UMEMOTO 		}
307f62c4786SHajimu UMEMOTO 		if (n > 0) {
308f62c4786SHajimu UMEMOTO 			DPRINTF(("get_soa: CNAME or DNAME found"));
309f62c4786SHajimu UMEMOTO 			sect = ns_s_max, n = 0;
310f62c4786SHajimu UMEMOTO 		} else {
311f62c4786SHajimu UMEMOTO 			rcode = ns_msg_getflag(msg, ns_f_rcode);
312f62c4786SHajimu UMEMOTO 			ancount = ns_msg_count(msg, ns_s_an);
313f62c4786SHajimu UMEMOTO 			nscount = ns_msg_count(msg, ns_s_ns);
314f62c4786SHajimu UMEMOTO 			if (ancount > 0 && rcode == ns_r_noerror)
315f62c4786SHajimu UMEMOTO 				sect = ns_s_an, n = ancount;
316f62c4786SHajimu UMEMOTO 			else if (nscount > 0)
317f62c4786SHajimu UMEMOTO 				sect = ns_s_ns, n = nscount;
318f62c4786SHajimu UMEMOTO 			else
319f62c4786SHajimu UMEMOTO 				sect = ns_s_max, n = 0;
320f62c4786SHajimu UMEMOTO 		}
321f62c4786SHajimu UMEMOTO 		for (i = 0; i < n; i++) {
322f62c4786SHajimu UMEMOTO 			const char *t;
323f62c4786SHajimu UMEMOTO 			const u_char *rdata;
324f62c4786SHajimu UMEMOTO 			ns_rr rr;
325f62c4786SHajimu UMEMOTO 
326f62c4786SHajimu UMEMOTO 			if (ns_parserr(&msg, sect, i, &rr) < 0) {
327f62c4786SHajimu UMEMOTO 				DPRINTF(("get_soa: ns_parserr(%s, %d) failed",
328f62c4786SHajimu UMEMOTO 					 p_section(sect, ns_o_query), i));
329f62c4786SHajimu UMEMOTO 				goto cleanup;
330f62c4786SHajimu UMEMOTO 			}
331f62c4786SHajimu UMEMOTO 			if (ns_rr_type(rr) == ns_t_cname ||
332f62c4786SHajimu UMEMOTO 			    ns_rr_type(rr) == ns_t_dname)
333f62c4786SHajimu UMEMOTO 				break;
334f62c4786SHajimu UMEMOTO 			if (ns_rr_type(rr) != ns_t_soa ||
335f62c4786SHajimu UMEMOTO 			    ns_rr_class(rr) != class)
336f62c4786SHajimu UMEMOTO 				continue;
337f62c4786SHajimu UMEMOTO 			t = ns_rr_name(rr);
338f62c4786SHajimu UMEMOTO 			switch (sect) {
339f62c4786SHajimu UMEMOTO 			case ns_s_an:
340f62c4786SHajimu UMEMOTO 				if (ns_samedomain(dname, t) == 0) {
341f62c4786SHajimu UMEMOTO 					DPRINTF(
342f62c4786SHajimu UMEMOTO 				    ("get_soa: ns_samedomain('%s', '%s') == 0",
343f62c4786SHajimu UMEMOTO 						dname, t)
344f62c4786SHajimu UMEMOTO 						);
345f62c4786SHajimu UMEMOTO 					errno = EPROTOTYPE;
346f62c4786SHajimu UMEMOTO 					goto cleanup;
347f62c4786SHajimu UMEMOTO 				}
348f62c4786SHajimu UMEMOTO 				break;
349f62c4786SHajimu UMEMOTO 			case ns_s_ns:
350f62c4786SHajimu UMEMOTO 				if (ns_samename(dname, t) == 1 ||
351f62c4786SHajimu UMEMOTO 				    ns_samedomain(dname, t) == 0) {
352f62c4786SHajimu UMEMOTO 					DPRINTF(
353f62c4786SHajimu UMEMOTO 		       ("get_soa: ns_samename() || !ns_samedomain('%s', '%s')",
354f62c4786SHajimu UMEMOTO 						dname, t)
355f62c4786SHajimu UMEMOTO 						);
356f62c4786SHajimu UMEMOTO 					errno = EPROTOTYPE;
357f62c4786SHajimu UMEMOTO 					goto cleanup;
358f62c4786SHajimu UMEMOTO 				}
359f62c4786SHajimu UMEMOTO 				break;
360f62c4786SHajimu UMEMOTO 			default:
361f62c4786SHajimu UMEMOTO 				abort();
362f62c4786SHajimu UMEMOTO 			}
363f62c4786SHajimu UMEMOTO 			if (strlen(t) + 1 > zsize) {
364f62c4786SHajimu UMEMOTO 				DPRINTF(("get_soa: zname(%lu) too small (%lu)",
365f62c4786SHajimu UMEMOTO 					 (unsigned long)zsize,
366f62c4786SHajimu UMEMOTO 					 (unsigned long)strlen(t) + 1));
367f62c4786SHajimu UMEMOTO 				errno = EMSGSIZE;
368f62c4786SHajimu UMEMOTO 				goto cleanup;
369f62c4786SHajimu UMEMOTO 			}
370f62c4786SHajimu UMEMOTO 			strcpy(zname, t);
371f62c4786SHajimu UMEMOTO 			rdata = ns_rr_rdata(rr);
372f62c4786SHajimu UMEMOTO 			if (ns_name_uncompress(resp, ns_msg_end(msg), rdata,
373f62c4786SHajimu UMEMOTO 					       mname, msize) < 0) {
374f62c4786SHajimu UMEMOTO 				DPRINTF(("get_soa: ns_name_uncompress failed")
375f62c4786SHajimu UMEMOTO 					);
376f62c4786SHajimu UMEMOTO 				goto cleanup;
377f62c4786SHajimu UMEMOTO 			}
378f62c4786SHajimu UMEMOTO 			if (save_ns(statp, &msg, ns_s_ns,
379f62c4786SHajimu UMEMOTO 				    zname, class, opts, nsrrsp) < 0) {
380f62c4786SHajimu UMEMOTO 				DPRINTF(("get_soa: save_ns failed"));
381f62c4786SHajimu UMEMOTO 				goto cleanup;
382f62c4786SHajimu UMEMOTO 			}
383f62c4786SHajimu UMEMOTO 			free(resp);
384f62c4786SHajimu UMEMOTO 			return (0);
385f62c4786SHajimu UMEMOTO 		}
386f62c4786SHajimu UMEMOTO 
387f62c4786SHajimu UMEMOTO 		/* If we're out of labels, then not even "." has an SOA! */
388f62c4786SHajimu UMEMOTO 		if (*dname == '\0')
389f62c4786SHajimu UMEMOTO 			break;
390f62c4786SHajimu UMEMOTO 
391f62c4786SHajimu UMEMOTO 		/* Find label-terminating "."; top of loop will skip it. */
392f62c4786SHajimu UMEMOTO 		while (*dname != '.') {
393f62c4786SHajimu UMEMOTO 			if (*dname == '\\')
394f62c4786SHajimu UMEMOTO 				if (*++dname == '\0') {
395f62c4786SHajimu UMEMOTO 					errno = EMSGSIZE;
396f62c4786SHajimu UMEMOTO 					goto cleanup;
397f62c4786SHajimu UMEMOTO 				}
398f62c4786SHajimu UMEMOTO 			dname++;
399f62c4786SHajimu UMEMOTO 		}
400f62c4786SHajimu UMEMOTO 	}
401f62c4786SHajimu UMEMOTO 	DPRINTF(("get_soa: out of labels"));
402f62c4786SHajimu UMEMOTO 	errno = EDESTADDRREQ;
403f62c4786SHajimu UMEMOTO  cleanup:
404f62c4786SHajimu UMEMOTO 	if (resp != NULL)
405f62c4786SHajimu UMEMOTO 		free(resp);
406f62c4786SHajimu UMEMOTO 	return (-1);
407f62c4786SHajimu UMEMOTO }
408f62c4786SHajimu UMEMOTO 
409f62c4786SHajimu UMEMOTO static int
get_ns(res_state statp,const char * zname,ns_class class,int opts,rrset_ns * nsrrsp)410f62c4786SHajimu UMEMOTO get_ns(res_state statp, const char *zname, ns_class class, int opts,
411f62c4786SHajimu UMEMOTO       rrset_ns *nsrrsp)
412f62c4786SHajimu UMEMOTO {
413f62c4786SHajimu UMEMOTO 	u_char *resp;
414f62c4786SHajimu UMEMOTO 	ns_msg msg;
415f62c4786SHajimu UMEMOTO 	int n;
416f62c4786SHajimu UMEMOTO 
417f62c4786SHajimu UMEMOTO 	resp = malloc(NS_MAXMSG);
418f62c4786SHajimu UMEMOTO 	if (resp == NULL)
419f62c4786SHajimu UMEMOTO 		return (-1);
420f62c4786SHajimu UMEMOTO 
421f62c4786SHajimu UMEMOTO 	/* Go and get the NS RRs for this zone. */
422f62c4786SHajimu UMEMOTO 	n = do_query(statp, zname, class, ns_t_ns, resp, &msg);
423f62c4786SHajimu UMEMOTO 	if (n != 0) {
424f62c4786SHajimu UMEMOTO 		DPRINTF(("get_ns: do_query('%s', %s) failed (%d)",
425f62c4786SHajimu UMEMOTO 			 zname, p_class(class), n));
426f62c4786SHajimu UMEMOTO 		free(resp);
427f62c4786SHajimu UMEMOTO 		return (-1);
428f62c4786SHajimu UMEMOTO 	}
429f62c4786SHajimu UMEMOTO 
430f62c4786SHajimu UMEMOTO 	/* Remember the NS RRs and associated A RRs that came back. */
431f62c4786SHajimu UMEMOTO 	if (save_ns(statp, &msg, ns_s_an, zname, class, opts, nsrrsp) < 0) {
432f62c4786SHajimu UMEMOTO 		DPRINTF(("get_ns save_ns('%s', %s) failed",
433f62c4786SHajimu UMEMOTO 			 zname, p_class(class)));
434f62c4786SHajimu UMEMOTO 		free(resp);
435f62c4786SHajimu UMEMOTO 		return (-1);
436f62c4786SHajimu UMEMOTO 	}
437f62c4786SHajimu UMEMOTO 
438f62c4786SHajimu UMEMOTO 	free(resp);
439f62c4786SHajimu UMEMOTO 	return (0);
440f62c4786SHajimu UMEMOTO }
441f62c4786SHajimu UMEMOTO 
442f62c4786SHajimu UMEMOTO static int
get_glue(res_state statp,ns_class class,int opts,rrset_ns * nsrrsp)443f62c4786SHajimu UMEMOTO get_glue(res_state statp, ns_class class, int opts, rrset_ns *nsrrsp) {
444f62c4786SHajimu UMEMOTO 	rr_ns *nsrr, *nsrr_n;
445f62c4786SHajimu UMEMOTO 	u_char *resp;
446f62c4786SHajimu UMEMOTO 
447f62c4786SHajimu UMEMOTO 	resp = malloc(NS_MAXMSG);
448f62c4786SHajimu UMEMOTO 	if (resp == NULL)
449f62c4786SHajimu UMEMOTO 		return(-1);
450f62c4786SHajimu UMEMOTO 
451f62c4786SHajimu UMEMOTO 	/* Go and get the A RRs for each empty NS RR on our list. */
452f62c4786SHajimu UMEMOTO 	for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) {
453f62c4786SHajimu UMEMOTO 		ns_msg msg;
454f62c4786SHajimu UMEMOTO 		int n;
455f62c4786SHajimu UMEMOTO 
456f62c4786SHajimu UMEMOTO 		nsrr_n = NEXT(nsrr, link);
457f62c4786SHajimu UMEMOTO 
458f62c4786SHajimu UMEMOTO 		if ((nsrr->flags & RR_NS_HAVE_V4) == 0) {
459f62c4786SHajimu UMEMOTO 			n = do_query(statp, nsrr->name, class, ns_t_a,
460f62c4786SHajimu UMEMOTO 				     resp, &msg);
461f62c4786SHajimu UMEMOTO 			if (n < 0) {
462f62c4786SHajimu UMEMOTO 				DPRINTF(
463f62c4786SHajimu UMEMOTO 				       ("get_glue: do_query('%s', %s') failed",
464f62c4786SHajimu UMEMOTO 					nsrr->name, p_class(class)));
465f62c4786SHajimu UMEMOTO 				goto cleanup;
466f62c4786SHajimu UMEMOTO 			}
467f62c4786SHajimu UMEMOTO 			if (n > 0) {
468f62c4786SHajimu UMEMOTO 				DPRINTF((
469f62c4786SHajimu UMEMOTO 			"get_glue: do_query('%s', %s') CNAME or DNAME found",
470f62c4786SHajimu UMEMOTO 					 nsrr->name, p_class(class)));
471f62c4786SHajimu UMEMOTO 			}
472f62c4786SHajimu UMEMOTO 			if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
473f62c4786SHajimu UMEMOTO 				   opts, nsrr) < 0) {
474f62c4786SHajimu UMEMOTO 				DPRINTF(("get_glue: save_r('%s', %s) failed",
475f62c4786SHajimu UMEMOTO 					 nsrr->name, p_class(class)));
476f62c4786SHajimu UMEMOTO 				goto cleanup;
477f62c4786SHajimu UMEMOTO 			}
478f62c4786SHajimu UMEMOTO 		}
479f62c4786SHajimu UMEMOTO 
480f62c4786SHajimu UMEMOTO 		if ((nsrr->flags & RR_NS_HAVE_V6) == 0) {
481f62c4786SHajimu UMEMOTO 			n = do_query(statp, nsrr->name, class, ns_t_aaaa,
482f62c4786SHajimu UMEMOTO 				     resp, &msg);
483f62c4786SHajimu UMEMOTO 			if (n < 0) {
484f62c4786SHajimu UMEMOTO 				DPRINTF(
485f62c4786SHajimu UMEMOTO 				       ("get_glue: do_query('%s', %s') failed",
486f62c4786SHajimu UMEMOTO 					nsrr->name, p_class(class)));
487f62c4786SHajimu UMEMOTO 				goto cleanup;
488f62c4786SHajimu UMEMOTO 			}
489f62c4786SHajimu UMEMOTO 			if (n > 0) {
490f62c4786SHajimu UMEMOTO 				DPRINTF((
491f62c4786SHajimu UMEMOTO 			"get_glue: do_query('%s', %s') CNAME or DNAME found",
492f62c4786SHajimu UMEMOTO 					 nsrr->name, p_class(class)));
493f62c4786SHajimu UMEMOTO 			}
494f62c4786SHajimu UMEMOTO 			if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
495f62c4786SHajimu UMEMOTO 				   opts, nsrr) < 0) {
496f62c4786SHajimu UMEMOTO 				DPRINTF(("get_glue: save_r('%s', %s) failed",
497f62c4786SHajimu UMEMOTO 					 nsrr->name, p_class(class)));
498f62c4786SHajimu UMEMOTO 				goto cleanup;
499f62c4786SHajimu UMEMOTO 			}
500f62c4786SHajimu UMEMOTO 		}
501f62c4786SHajimu UMEMOTO 
502f62c4786SHajimu UMEMOTO 		/* If it's still empty, it's just chaff. */
503f62c4786SHajimu UMEMOTO 		if (EMPTY(nsrr->addrs)) {
504f62c4786SHajimu UMEMOTO 			DPRINTF(("get_glue: removing empty '%s' NS",
505f62c4786SHajimu UMEMOTO 				 nsrr->name));
506f62c4786SHajimu UMEMOTO 			free_nsrr(nsrrsp, nsrr);
507f62c4786SHajimu UMEMOTO 		}
508f62c4786SHajimu UMEMOTO 	}
509f62c4786SHajimu UMEMOTO 	free(resp);
510f62c4786SHajimu UMEMOTO 	return (0);
511f62c4786SHajimu UMEMOTO 
512f62c4786SHajimu UMEMOTO  cleanup:
513f62c4786SHajimu UMEMOTO 	free(resp);
514f62c4786SHajimu UMEMOTO 	return (-1);
515f62c4786SHajimu UMEMOTO }
516f62c4786SHajimu UMEMOTO 
517f62c4786SHajimu UMEMOTO static int
save_ns(res_state statp,ns_msg * msg,ns_sect sect,const char * owner,ns_class class,int opts,rrset_ns * nsrrsp)518f62c4786SHajimu UMEMOTO save_ns(res_state statp, ns_msg *msg, ns_sect sect,
519f62c4786SHajimu UMEMOTO 	const char *owner, ns_class class, int opts,
520f62c4786SHajimu UMEMOTO 	rrset_ns *nsrrsp)
521f62c4786SHajimu UMEMOTO {
522f62c4786SHajimu UMEMOTO 	int i;
523f62c4786SHajimu UMEMOTO 
524f62c4786SHajimu UMEMOTO 	for (i = 0; i < ns_msg_count(*msg, sect); i++) {
525f62c4786SHajimu UMEMOTO 		char tname[MAXDNAME];
526f62c4786SHajimu UMEMOTO 		const u_char *rdata;
527f62c4786SHajimu UMEMOTO 		rr_ns *nsrr;
528f62c4786SHajimu UMEMOTO 		ns_rr rr;
529f62c4786SHajimu UMEMOTO 
530f62c4786SHajimu UMEMOTO 		if (ns_parserr(msg, sect, i, &rr) < 0) {
531f62c4786SHajimu UMEMOTO 			DPRINTF(("save_ns: ns_parserr(%s, %d) failed",
532f62c4786SHajimu UMEMOTO 				 p_section(sect, ns_o_query), i));
533f62c4786SHajimu UMEMOTO 			return (-1);
534f62c4786SHajimu UMEMOTO 		}
535f62c4786SHajimu UMEMOTO 		if (ns_rr_type(rr) != ns_t_ns ||
536f62c4786SHajimu UMEMOTO 		    ns_rr_class(rr) != class ||
537f62c4786SHajimu UMEMOTO 		    ns_samename(ns_rr_name(rr), owner) != 1)
538f62c4786SHajimu UMEMOTO 			continue;
539f62c4786SHajimu UMEMOTO 		nsrr = find_ns(nsrrsp, ns_rr_name(rr));
540f62c4786SHajimu UMEMOTO 		if (nsrr == NULL) {
541f62c4786SHajimu UMEMOTO 			nsrr = malloc(sizeof *nsrr);
542f62c4786SHajimu UMEMOTO 			if (nsrr == NULL) {
543f62c4786SHajimu UMEMOTO 				DPRINTF(("save_ns: malloc failed"));
544f62c4786SHajimu UMEMOTO 				return (-1);
545f62c4786SHajimu UMEMOTO 			}
546f62c4786SHajimu UMEMOTO 			rdata = ns_rr_rdata(rr);
547f62c4786SHajimu UMEMOTO 			if (ns_name_uncompress(ns_msg_base(*msg),
548f62c4786SHajimu UMEMOTO 					       ns_msg_end(*msg), rdata,
549f62c4786SHajimu UMEMOTO 					       tname, sizeof tname) < 0) {
550f62c4786SHajimu UMEMOTO 				DPRINTF(("save_ns: ns_name_uncompress failed")
551f62c4786SHajimu UMEMOTO 					);
552f62c4786SHajimu UMEMOTO 				free(nsrr);
553f62c4786SHajimu UMEMOTO 				return (-1);
554f62c4786SHajimu UMEMOTO 			}
555f62c4786SHajimu UMEMOTO 			nsrr->name = strdup(tname);
556f62c4786SHajimu UMEMOTO 			if (nsrr->name == NULL) {
557f62c4786SHajimu UMEMOTO 				DPRINTF(("save_ns: strdup failed"));
558f62c4786SHajimu UMEMOTO 				free(nsrr);
559f62c4786SHajimu UMEMOTO 				return (-1);
560f62c4786SHajimu UMEMOTO 			}
561f62c4786SHajimu UMEMOTO 			INIT_LINK(nsrr, link);
562f62c4786SHajimu UMEMOTO 			INIT_LIST(nsrr->addrs);
563f62c4786SHajimu UMEMOTO 			nsrr->flags = 0;
564f62c4786SHajimu UMEMOTO 			APPEND(*nsrrsp, nsrr, link);
565f62c4786SHajimu UMEMOTO 		}
566f62c4786SHajimu UMEMOTO 		if (save_a(statp, msg, ns_s_ar,
567f62c4786SHajimu UMEMOTO 			   nsrr->name, class, opts, nsrr) < 0) {
568f62c4786SHajimu UMEMOTO 			DPRINTF(("save_ns: save_r('%s', %s) failed",
569f62c4786SHajimu UMEMOTO 				 nsrr->name, p_class(class)));
570f62c4786SHajimu UMEMOTO 			return (-1);
571f62c4786SHajimu UMEMOTO 		}
572f62c4786SHajimu UMEMOTO 	}
573f62c4786SHajimu UMEMOTO 	return (0);
574f62c4786SHajimu UMEMOTO }
575f62c4786SHajimu UMEMOTO 
576f62c4786SHajimu UMEMOTO static int
save_a(res_state statp,ns_msg * msg,ns_sect sect,const char * owner,ns_class class,int opts,rr_ns * nsrr)577f62c4786SHajimu UMEMOTO save_a(res_state statp, ns_msg *msg, ns_sect sect,
578f62c4786SHajimu UMEMOTO        const char *owner, ns_class class, int opts,
579f62c4786SHajimu UMEMOTO        rr_ns *nsrr)
580f62c4786SHajimu UMEMOTO {
581f62c4786SHajimu UMEMOTO 	int i;
582f62c4786SHajimu UMEMOTO 
583f62c4786SHajimu UMEMOTO 	for (i = 0; i < ns_msg_count(*msg, sect); i++) {
584f62c4786SHajimu UMEMOTO 		ns_rr rr;
585f62c4786SHajimu UMEMOTO 		rr_a *arr;
586f62c4786SHajimu UMEMOTO 
587f62c4786SHajimu UMEMOTO 		if (ns_parserr(msg, sect, i, &rr) < 0) {
588f62c4786SHajimu UMEMOTO 			DPRINTF(("save_a: ns_parserr(%s, %d) failed",
589f62c4786SHajimu UMEMOTO 				 p_section(sect, ns_o_query), i));
590f62c4786SHajimu UMEMOTO 			return (-1);
591f62c4786SHajimu UMEMOTO 		}
592f62c4786SHajimu UMEMOTO 		if ((ns_rr_type(rr) != ns_t_a &&
593f62c4786SHajimu UMEMOTO 		     ns_rr_type(rr) != ns_t_aaaa) ||
594f62c4786SHajimu UMEMOTO 		    ns_rr_class(rr) != class ||
595f62c4786SHajimu UMEMOTO 		    ns_samename(ns_rr_name(rr), owner) != 1 ||
596f62c4786SHajimu UMEMOTO 		    ns_rr_rdlen(rr) != NS_INADDRSZ)
597f62c4786SHajimu UMEMOTO 			continue;
598f62c4786SHajimu UMEMOTO 		if ((opts & RES_IPV6ONLY) != 0 && ns_rr_type(rr) != ns_t_aaaa)
599f62c4786SHajimu UMEMOTO 			continue;
600f62c4786SHajimu UMEMOTO 		if ((opts & RES_IPV4ONLY) != 0 && ns_rr_type(rr) != ns_t_a)
601f62c4786SHajimu UMEMOTO 			continue;
602f62c4786SHajimu UMEMOTO 		arr = malloc(sizeof *arr);
603f62c4786SHajimu UMEMOTO 		if (arr == NULL) {
604f62c4786SHajimu UMEMOTO 			DPRINTF(("save_a: malloc failed"));
605f62c4786SHajimu UMEMOTO 			return (-1);
606f62c4786SHajimu UMEMOTO 		}
607f62c4786SHajimu UMEMOTO 		INIT_LINK(arr, link);
608f62c4786SHajimu UMEMOTO 		memset(&arr->addr, 0, sizeof(arr->addr));
609f62c4786SHajimu UMEMOTO 		switch (ns_rr_type(rr)) {
610f62c4786SHajimu UMEMOTO 		case ns_t_a:
611f62c4786SHajimu UMEMOTO 			arr->addr.sin.sin_family = AF_INET;
612f62c4786SHajimu UMEMOTO #ifdef HAVE_SA_LEN
613f62c4786SHajimu UMEMOTO 			arr->addr.sin.sin_len = sizeof(arr->addr.sin);
614f62c4786SHajimu UMEMOTO #endif
615f62c4786SHajimu UMEMOTO 			memcpy(&arr->addr.sin.sin_addr, ns_rr_rdata(rr),
616f62c4786SHajimu UMEMOTO 			       NS_INADDRSZ);
617f62c4786SHajimu UMEMOTO 			arr->addr.sin.sin_port = htons(NAMESERVER_PORT);
618f62c4786SHajimu UMEMOTO 			nsrr->flags |= RR_NS_HAVE_V4;
619f62c4786SHajimu UMEMOTO 			break;
620f62c4786SHajimu UMEMOTO 		case ns_t_aaaa:
621f62c4786SHajimu UMEMOTO 			arr->addr.sin6.sin6_family = AF_INET6;
622f62c4786SHajimu UMEMOTO #ifdef HAVE_SA_LEN
623f62c4786SHajimu UMEMOTO 			arr->addr.sin6.sin6_len = sizeof(arr->addr.sin6);
624f62c4786SHajimu UMEMOTO #endif
625f62c4786SHajimu UMEMOTO 			memcpy(&arr->addr.sin6.sin6_addr, ns_rr_rdata(rr), 16);
62696b38943SBjoern A. Zeeb 			arr->addr.sin6.sin6_port = htons(NAMESERVER_PORT);
627f62c4786SHajimu UMEMOTO 			nsrr->flags |= RR_NS_HAVE_V6;
628f62c4786SHajimu UMEMOTO 			break;
629f62c4786SHajimu UMEMOTO 		default:
630f62c4786SHajimu UMEMOTO 			abort();
631f62c4786SHajimu UMEMOTO 		}
632f62c4786SHajimu UMEMOTO 		APPEND(nsrr->addrs, arr, link);
633f62c4786SHajimu UMEMOTO 	}
634f62c4786SHajimu UMEMOTO 	return (0);
635f62c4786SHajimu UMEMOTO }
636f62c4786SHajimu UMEMOTO 
637f62c4786SHajimu UMEMOTO static void
free_nsrrset(rrset_ns * nsrrsp)638f62c4786SHajimu UMEMOTO free_nsrrset(rrset_ns *nsrrsp) {
639f62c4786SHajimu UMEMOTO 	rr_ns *nsrr;
640f62c4786SHajimu UMEMOTO 
641f62c4786SHajimu UMEMOTO 	while ((nsrr = HEAD(*nsrrsp)) != NULL)
642f62c4786SHajimu UMEMOTO 		free_nsrr(nsrrsp, nsrr);
643f62c4786SHajimu UMEMOTO }
644f62c4786SHajimu UMEMOTO 
645f62c4786SHajimu UMEMOTO static void
free_nsrr(rrset_ns * nsrrsp,rr_ns * nsrr)646f62c4786SHajimu UMEMOTO free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) {
647f62c4786SHajimu UMEMOTO 	rr_a *arr;
648f62c4786SHajimu UMEMOTO 	char *tmp;
649f62c4786SHajimu UMEMOTO 
650f62c4786SHajimu UMEMOTO 	while ((arr = HEAD(nsrr->addrs)) != NULL) {
651f62c4786SHajimu UMEMOTO 		UNLINK(nsrr->addrs, arr, link);
652f62c4786SHajimu UMEMOTO 		free(arr);
653f62c4786SHajimu UMEMOTO 	}
654f62c4786SHajimu UMEMOTO 	DE_CONST(nsrr->name, tmp);
655f62c4786SHajimu UMEMOTO 	free(tmp);
656f62c4786SHajimu UMEMOTO 	UNLINK(*nsrrsp, nsrr, link);
657f62c4786SHajimu UMEMOTO 	free(nsrr);
658f62c4786SHajimu UMEMOTO }
659f62c4786SHajimu UMEMOTO 
660f62c4786SHajimu UMEMOTO static rr_ns *
find_ns(rrset_ns * nsrrsp,const char * dname)661f62c4786SHajimu UMEMOTO find_ns(rrset_ns *nsrrsp, const char *dname) {
662f62c4786SHajimu UMEMOTO 	rr_ns *nsrr;
663f62c4786SHajimu UMEMOTO 
664f62c4786SHajimu UMEMOTO 	for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = NEXT(nsrr, link))
665f62c4786SHajimu UMEMOTO 		if (ns_samename(nsrr->name, dname) == 1)
666f62c4786SHajimu UMEMOTO 			return (nsrr);
667f62c4786SHajimu UMEMOTO 	return (NULL);
668f62c4786SHajimu UMEMOTO }
669f62c4786SHajimu UMEMOTO 
670f62c4786SHajimu UMEMOTO static int
do_query(res_state statp,const char * dname,ns_class class,ns_type qtype,u_char * resp,ns_msg * msg)671f62c4786SHajimu UMEMOTO do_query(res_state statp, const char *dname, ns_class class, ns_type qtype,
672f62c4786SHajimu UMEMOTO 	 u_char *resp, ns_msg *msg)
673f62c4786SHajimu UMEMOTO {
674f62c4786SHajimu UMEMOTO 	u_char req[NS_PACKETSZ];
675f62c4786SHajimu UMEMOTO 	int i, n;
676f62c4786SHajimu UMEMOTO 
677f62c4786SHajimu UMEMOTO 	n = res_nmkquery(statp, ns_o_query, dname, class, qtype,
678f62c4786SHajimu UMEMOTO 			 NULL, 0, NULL, req, NS_PACKETSZ);
679f62c4786SHajimu UMEMOTO 	if (n < 0) {
680f62c4786SHajimu UMEMOTO 		DPRINTF(("do_query: res_nmkquery failed"));
681f62c4786SHajimu UMEMOTO 		return (-1);
682f62c4786SHajimu UMEMOTO 	}
683f62c4786SHajimu UMEMOTO 	n = res_nsend(statp, req, n, resp, NS_MAXMSG);
684f62c4786SHajimu UMEMOTO 	if (n < 0) {
685f62c4786SHajimu UMEMOTO 		DPRINTF(("do_query: res_nsend failed"));
686f62c4786SHajimu UMEMOTO 		return (-1);
687f62c4786SHajimu UMEMOTO 	}
688f62c4786SHajimu UMEMOTO 	if (n == 0) {
689f62c4786SHajimu UMEMOTO 		DPRINTF(("do_query: res_nsend returned 0"));
690f62c4786SHajimu UMEMOTO 		errno = EMSGSIZE;
691f62c4786SHajimu UMEMOTO 		return (-1);
692f62c4786SHajimu UMEMOTO 	}
693f62c4786SHajimu UMEMOTO 	if (ns_initparse(resp, n, msg) < 0) {
694f62c4786SHajimu UMEMOTO 		DPRINTF(("do_query: ns_initparse failed"));
695f62c4786SHajimu UMEMOTO 		return (-1);
696f62c4786SHajimu UMEMOTO 	}
697f62c4786SHajimu UMEMOTO 	n = 0;
698f62c4786SHajimu UMEMOTO 	for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) {
699f62c4786SHajimu UMEMOTO 		ns_rr rr;
700f62c4786SHajimu UMEMOTO 
701f62c4786SHajimu UMEMOTO 		if (ns_parserr(msg, ns_s_an, i, &rr) < 0) {
702f62c4786SHajimu UMEMOTO 			DPRINTF(("do_query: ns_parserr failed"));
703f62c4786SHajimu UMEMOTO 			return (-1);
704f62c4786SHajimu UMEMOTO 		}
705f62c4786SHajimu UMEMOTO 		n += (ns_rr_class(rr) == class &&
706f62c4786SHajimu UMEMOTO 		      (ns_rr_type(rr) == ns_t_cname ||
707f62c4786SHajimu UMEMOTO 		       ns_rr_type(rr) == ns_t_dname));
708f62c4786SHajimu UMEMOTO 	}
709f62c4786SHajimu UMEMOTO 	return (n);
710f62c4786SHajimu UMEMOTO }
711f62c4786SHajimu UMEMOTO 
712f62c4786SHajimu UMEMOTO static void
res_dprintf(const char * fmt,...)713f62c4786SHajimu UMEMOTO res_dprintf(const char *fmt, ...) {
714f62c4786SHajimu UMEMOTO 	va_list ap;
715f62c4786SHajimu UMEMOTO 
716f62c4786SHajimu UMEMOTO 	va_start(ap, fmt);
717f62c4786SHajimu UMEMOTO 	fputs(";; res_findzonecut: ", stderr);
718f62c4786SHajimu UMEMOTO 	vfprintf(stderr, fmt, ap);
719f62c4786SHajimu UMEMOTO 	fputc('\n', stderr);
720f62c4786SHajimu UMEMOTO 	va_end(ap);
721f62c4786SHajimu UMEMOTO }
722dde4a85dSHajimu UMEMOTO 
723dde4a85dSHajimu UMEMOTO /*! \file */
724