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