xref: /minix/external/bsd/bind/dist/lib/dns/rootns.c (revision 00b67f09)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: rootns.c,v 1.9 2015/07/08 17:28:59 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2005, 2007, 2008, 2010, 2012-2015  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2002  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: rootns.c,v 1.40.476.1 2012/02/07 00:44:14 each Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
27*00b67f09SDavid van Moolenbroek #include <isc/string.h>		/* Required for HP/UX (and others?) */
28*00b67f09SDavid van Moolenbroek #include <isc/util.h>
29*00b67f09SDavid van Moolenbroek 
30*00b67f09SDavid van Moolenbroek #include <dns/callbacks.h>
31*00b67f09SDavid van Moolenbroek #include <dns/db.h>
32*00b67f09SDavid van Moolenbroek #include <dns/dbiterator.h>
33*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
34*00b67f09SDavid van Moolenbroek #include <dns/log.h>
35*00b67f09SDavid van Moolenbroek #include <dns/master.h>
36*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
37*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
38*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
39*00b67f09SDavid van Moolenbroek #include <dns/rdatasetiter.h>
40*00b67f09SDavid van Moolenbroek #include <dns/rdatastruct.h>
41*00b67f09SDavid van Moolenbroek #include <dns/rdatatype.h>
42*00b67f09SDavid van Moolenbroek #include <dns/result.h>
43*00b67f09SDavid van Moolenbroek #include <dns/rootns.h>
44*00b67f09SDavid van Moolenbroek #include <dns/view.h>
45*00b67f09SDavid van Moolenbroek 
46*00b67f09SDavid van Moolenbroek static char root_ns[] =
47*00b67f09SDavid van Moolenbroek ";\n"
48*00b67f09SDavid van Moolenbroek "; Internet Root Nameservers\n"
49*00b67f09SDavid van Moolenbroek ";\n"
50*00b67f09SDavid van Moolenbroek "$TTL 518400\n"
51*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      A.ROOT-SERVERS.NET.\n"
52*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      B.ROOT-SERVERS.NET.\n"
53*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      C.ROOT-SERVERS.NET.\n"
54*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      D.ROOT-SERVERS.NET.\n"
55*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      E.ROOT-SERVERS.NET.\n"
56*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      F.ROOT-SERVERS.NET.\n"
57*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      G.ROOT-SERVERS.NET.\n"
58*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      H.ROOT-SERVERS.NET.\n"
59*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      I.ROOT-SERVERS.NET.\n"
60*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      J.ROOT-SERVERS.NET.\n"
61*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      K.ROOT-SERVERS.NET.\n"
62*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      L.ROOT-SERVERS.NET.\n"
63*00b67f09SDavid van Moolenbroek ".                       518400  IN      NS      M.ROOT-SERVERS.NET.\n"
64*00b67f09SDavid van Moolenbroek "A.ROOT-SERVERS.NET.     3600000 IN      A       198.41.0.4\n"
65*00b67f09SDavid van Moolenbroek "A.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:503:BA3E::2:30\n"
66*00b67f09SDavid van Moolenbroek "B.ROOT-SERVERS.NET.     3600000 IN      A       192.228.79.201\n"
67*00b67f09SDavid van Moolenbroek "C.ROOT-SERVERS.NET.     3600000 IN      A       192.33.4.12\n"
68*00b67f09SDavid van Moolenbroek "C.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:500:2::c\n"
69*00b67f09SDavid van Moolenbroek "D.ROOT-SERVERS.NET.     3600000 IN      A       199.7.91.13\n"
70*00b67f09SDavid van Moolenbroek "D.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:500:2d::d\n"
71*00b67f09SDavid van Moolenbroek "E.ROOT-SERVERS.NET.     3600000 IN      A       192.203.230.10\n"
72*00b67f09SDavid van Moolenbroek "F.ROOT-SERVERS.NET.     3600000 IN      A       192.5.5.241\n"
73*00b67f09SDavid van Moolenbroek "F.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:500:2F::F\n"
74*00b67f09SDavid van Moolenbroek "G.ROOT-SERVERS.NET.     3600000 IN      A       192.112.36.4\n"
75*00b67f09SDavid van Moolenbroek "H.ROOT-SERVERS.NET.     3600000 IN      A       128.63.2.53\n"
76*00b67f09SDavid van Moolenbroek "H.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:500:1::803F:235\n"
77*00b67f09SDavid van Moolenbroek "I.ROOT-SERVERS.NET.     3600000 IN      A       192.36.148.17\n"
78*00b67f09SDavid van Moolenbroek "I.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:7fe::53\n"
79*00b67f09SDavid van Moolenbroek "J.ROOT-SERVERS.NET.     3600000 IN      A       192.58.128.30\n"
80*00b67f09SDavid van Moolenbroek "J.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:503:C27::2:30\n"
81*00b67f09SDavid van Moolenbroek "K.ROOT-SERVERS.NET.     3600000 IN      A       193.0.14.129\n"
82*00b67f09SDavid van Moolenbroek "K.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:7FD::1\n"
83*00b67f09SDavid van Moolenbroek "L.ROOT-SERVERS.NET.     3600000 IN      A       199.7.83.42\n"
84*00b67f09SDavid van Moolenbroek "L.ROOT-SERVERS.NET.     604800  IN      AAAA    2001:500:3::42\n"
85*00b67f09SDavid van Moolenbroek "M.ROOT-SERVERS.NET.     3600000 IN      A       202.12.27.33\n"
86*00b67f09SDavid van Moolenbroek "M.ROOT-SERVERS.NET.     3600000 IN      AAAA    2001:DC3::35\n";
87*00b67f09SDavid van Moolenbroek 
88*00b67f09SDavid van Moolenbroek static isc_result_t
in_rootns(dns_rdataset_t * rootns,dns_name_t * name)89*00b67f09SDavid van Moolenbroek in_rootns(dns_rdataset_t *rootns, dns_name_t *name) {
90*00b67f09SDavid van Moolenbroek 	isc_result_t result;
91*00b67f09SDavid van Moolenbroek 	dns_rdata_t rdata = DNS_RDATA_INIT;
92*00b67f09SDavid van Moolenbroek 	dns_rdata_ns_t ns;
93*00b67f09SDavid van Moolenbroek 
94*00b67f09SDavid van Moolenbroek 	if (!dns_rdataset_isassociated(rootns))
95*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
96*00b67f09SDavid van Moolenbroek 
97*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(rootns);
98*00b67f09SDavid van Moolenbroek 	while (result == ISC_R_SUCCESS) {
99*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(rootns, &rdata);
100*00b67f09SDavid van Moolenbroek 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
101*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
102*00b67f09SDavid van Moolenbroek 			return (result);
103*00b67f09SDavid van Moolenbroek 		if (dns_name_compare(name, &ns.name) == 0)
104*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
105*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_next(rootns);
106*00b67f09SDavid van Moolenbroek 		dns_rdata_reset(&rdata);
107*00b67f09SDavid van Moolenbroek 	}
108*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOMORE)
109*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOTFOUND;
110*00b67f09SDavid van Moolenbroek 	return (result);
111*00b67f09SDavid van Moolenbroek }
112*00b67f09SDavid van Moolenbroek 
113*00b67f09SDavid van Moolenbroek static isc_result_t
check_node(dns_rdataset_t * rootns,dns_name_t * name,dns_rdatasetiter_t * rdsiter)114*00b67f09SDavid van Moolenbroek check_node(dns_rdataset_t *rootns, dns_name_t *name,
115*00b67f09SDavid van Moolenbroek 	   dns_rdatasetiter_t *rdsiter) {
116*00b67f09SDavid van Moolenbroek 	isc_result_t result;
117*00b67f09SDavid van Moolenbroek 	dns_rdataset_t rdataset;
118*00b67f09SDavid van Moolenbroek 
119*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&rdataset);
120*00b67f09SDavid van Moolenbroek 	result = dns_rdatasetiter_first(rdsiter);
121*00b67f09SDavid van Moolenbroek 	while (result == ISC_R_SUCCESS) {
122*00b67f09SDavid van Moolenbroek 		dns_rdatasetiter_current(rdsiter, &rdataset);
123*00b67f09SDavid van Moolenbroek 		switch (rdataset.type) {
124*00b67f09SDavid van Moolenbroek 		case dns_rdatatype_a:
125*00b67f09SDavid van Moolenbroek 		case dns_rdatatype_aaaa:
126*00b67f09SDavid van Moolenbroek 			result = in_rootns(rootns, name);
127*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
128*00b67f09SDavid van Moolenbroek 				goto cleanup;
129*00b67f09SDavid van Moolenbroek 			break;
130*00b67f09SDavid van Moolenbroek 		case dns_rdatatype_ns:
131*00b67f09SDavid van Moolenbroek 			if (dns_name_compare(name, dns_rootname) == 0)
132*00b67f09SDavid van Moolenbroek 				break;
133*00b67f09SDavid van Moolenbroek 			/*FALLTHROUGH*/
134*00b67f09SDavid van Moolenbroek 		default:
135*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
136*00b67f09SDavid van Moolenbroek 			goto cleanup;
137*00b67f09SDavid van Moolenbroek 		}
138*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rdataset);
139*00b67f09SDavid van Moolenbroek 		result = dns_rdatasetiter_next(rdsiter);
140*00b67f09SDavid van Moolenbroek 	}
141*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOMORE)
142*00b67f09SDavid van Moolenbroek 		result = ISC_R_SUCCESS;
143*00b67f09SDavid van Moolenbroek  cleanup:
144*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&rdataset))
145*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rdataset);
146*00b67f09SDavid van Moolenbroek 	return (result);
147*00b67f09SDavid van Moolenbroek }
148*00b67f09SDavid van Moolenbroek 
149*00b67f09SDavid van Moolenbroek static isc_result_t
check_hints(dns_db_t * db)150*00b67f09SDavid van Moolenbroek check_hints(dns_db_t *db) {
151*00b67f09SDavid van Moolenbroek 	isc_result_t result;
152*00b67f09SDavid van Moolenbroek 	dns_rdataset_t rootns;
153*00b67f09SDavid van Moolenbroek 	dns_dbiterator_t *dbiter = NULL;
154*00b67f09SDavid van Moolenbroek 	dns_dbnode_t *node = NULL;
155*00b67f09SDavid van Moolenbroek 	isc_stdtime_t now;
156*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixname;
157*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
158*00b67f09SDavid van Moolenbroek 	dns_rdatasetiter_t *rdsiter = NULL;
159*00b67f09SDavid van Moolenbroek 
160*00b67f09SDavid van Moolenbroek 	isc_stdtime_get(&now);
161*00b67f09SDavid van Moolenbroek 
162*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixname);
163*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fixname);
164*00b67f09SDavid van Moolenbroek 
165*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&rootns);
166*00b67f09SDavid van Moolenbroek 	(void)dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0,
167*00b67f09SDavid van Moolenbroek 			  now, NULL, name, &rootns, NULL);
168*00b67f09SDavid van Moolenbroek 	result = dns_db_createiterator(db, 0, &dbiter);
169*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
170*00b67f09SDavid van Moolenbroek 		goto cleanup;
171*00b67f09SDavid van Moolenbroek 	result = dns_dbiterator_first(dbiter);
172*00b67f09SDavid van Moolenbroek 	while (result == ISC_R_SUCCESS) {
173*00b67f09SDavid van Moolenbroek 		result = dns_dbiterator_current(dbiter, &node, name);
174*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
175*00b67f09SDavid van Moolenbroek 			goto cleanup;
176*00b67f09SDavid van Moolenbroek 		result = dns_db_allrdatasets(db, node, NULL, now, &rdsiter);
177*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
178*00b67f09SDavid van Moolenbroek 			goto cleanup;
179*00b67f09SDavid van Moolenbroek 		result = check_node(&rootns, name, rdsiter);
180*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
181*00b67f09SDavid van Moolenbroek 			goto cleanup;
182*00b67f09SDavid van Moolenbroek 		dns_rdatasetiter_destroy(&rdsiter);
183*00b67f09SDavid van Moolenbroek 		dns_db_detachnode(db, &node);
184*00b67f09SDavid van Moolenbroek 		result = dns_dbiterator_next(dbiter);
185*00b67f09SDavid van Moolenbroek 	}
186*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOMORE)
187*00b67f09SDavid van Moolenbroek 		result = ISC_R_SUCCESS;
188*00b67f09SDavid van Moolenbroek 
189*00b67f09SDavid van Moolenbroek  cleanup:
190*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&rootns))
191*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rootns);
192*00b67f09SDavid van Moolenbroek 	if (rdsiter != NULL)
193*00b67f09SDavid van Moolenbroek 		dns_rdatasetiter_destroy(&rdsiter);
194*00b67f09SDavid van Moolenbroek 	if (node != NULL)
195*00b67f09SDavid van Moolenbroek 		dns_db_detachnode(db, &node);
196*00b67f09SDavid van Moolenbroek 	if (dbiter != NULL)
197*00b67f09SDavid van Moolenbroek 		dns_dbiterator_destroy(&dbiter);
198*00b67f09SDavid van Moolenbroek 	return (result);
199*00b67f09SDavid van Moolenbroek }
200*00b67f09SDavid van Moolenbroek 
201*00b67f09SDavid van Moolenbroek isc_result_t
dns_rootns_create(isc_mem_t * mctx,dns_rdataclass_t rdclass,const char * filename,dns_db_t ** target)202*00b67f09SDavid van Moolenbroek dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
203*00b67f09SDavid van Moolenbroek 		  const char *filename, dns_db_t **target)
204*00b67f09SDavid van Moolenbroek {
205*00b67f09SDavid van Moolenbroek 	isc_result_t result, eresult;
206*00b67f09SDavid van Moolenbroek 	isc_buffer_t source;
207*00b67f09SDavid van Moolenbroek 	unsigned int len;
208*00b67f09SDavid van Moolenbroek 	dns_rdatacallbacks_t callbacks;
209*00b67f09SDavid van Moolenbroek 	dns_db_t *db = NULL;
210*00b67f09SDavid van Moolenbroek 
211*00b67f09SDavid van Moolenbroek 	REQUIRE(target != NULL && *target == NULL);
212*00b67f09SDavid van Moolenbroek 
213*00b67f09SDavid van Moolenbroek 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
214*00b67f09SDavid van Moolenbroek 			       rdclass, 0, NULL, &db);
215*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
216*00b67f09SDavid van Moolenbroek 		goto failure;
217*00b67f09SDavid van Moolenbroek 
218*00b67f09SDavid van Moolenbroek 	len = strlen(root_ns);
219*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&source, root_ns, len);
220*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&source, len);
221*00b67f09SDavid van Moolenbroek 
222*00b67f09SDavid van Moolenbroek 	dns_rdatacallbacks_init(&callbacks);
223*00b67f09SDavid van Moolenbroek 	result = dns_db_beginload(db, &callbacks);
224*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
225*00b67f09SDavid van Moolenbroek 		goto failure;
226*00b67f09SDavid van Moolenbroek 	if (filename != NULL) {
227*00b67f09SDavid van Moolenbroek 		/*
228*00b67f09SDavid van Moolenbroek 		 * Load the hints from the specified filename.
229*00b67f09SDavid van Moolenbroek 		 */
230*00b67f09SDavid van Moolenbroek 		result = dns_master_loadfile(filename, &db->origin,
231*00b67f09SDavid van Moolenbroek 					     &db->origin, db->rdclass,
232*00b67f09SDavid van Moolenbroek 					     DNS_MASTER_HINT,
233*00b67f09SDavid van Moolenbroek 					     &callbacks, db->mctx);
234*00b67f09SDavid van Moolenbroek 	} else if (rdclass == dns_rdataclass_in) {
235*00b67f09SDavid van Moolenbroek 		/*
236*00b67f09SDavid van Moolenbroek 		 * Default to using the Internet root servers.
237*00b67f09SDavid van Moolenbroek 		 */
238*00b67f09SDavid van Moolenbroek 		result = dns_master_loadbuffer(&source, &db->origin,
239*00b67f09SDavid van Moolenbroek 					       &db->origin, db->rdclass,
240*00b67f09SDavid van Moolenbroek 					       DNS_MASTER_HINT,
241*00b67f09SDavid van Moolenbroek 					       &callbacks, db->mctx);
242*00b67f09SDavid van Moolenbroek 	} else
243*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOTFOUND;
244*00b67f09SDavid van Moolenbroek 	eresult = dns_db_endload(db, &callbacks);
245*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)
246*00b67f09SDavid van Moolenbroek 		result = eresult;
247*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
248*00b67f09SDavid van Moolenbroek 		goto failure;
249*00b67f09SDavid van Moolenbroek 	if (check_hints(db) != ISC_R_SUCCESS)
250*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
251*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
252*00b67f09SDavid van Moolenbroek 			      "extra data in root hints '%s'",
253*00b67f09SDavid van Moolenbroek 			      (filename != NULL) ? filename : "<BUILT-IN>");
254*00b67f09SDavid van Moolenbroek 	*target = db;
255*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
256*00b67f09SDavid van Moolenbroek 
257*00b67f09SDavid van Moolenbroek  failure:
258*00b67f09SDavid van Moolenbroek 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS,
259*00b67f09SDavid van Moolenbroek 		      ISC_LOG_ERROR, "could not configure root hints from "
260*00b67f09SDavid van Moolenbroek 		      "'%s': %s", (filename != NULL) ? filename : "<BUILT-IN>",
261*00b67f09SDavid van Moolenbroek 		      isc_result_totext(result));
262*00b67f09SDavid van Moolenbroek 
263*00b67f09SDavid van Moolenbroek 	if (db != NULL)
264*00b67f09SDavid van Moolenbroek 		dns_db_detach(&db);
265*00b67f09SDavid van Moolenbroek 
266*00b67f09SDavid van Moolenbroek 	return (result);
267*00b67f09SDavid van Moolenbroek }
268*00b67f09SDavid van Moolenbroek 
269*00b67f09SDavid van Moolenbroek static void
report(dns_view_t * view,dns_name_t * name,isc_boolean_t missing,dns_rdata_t * rdata)270*00b67f09SDavid van Moolenbroek report(dns_view_t *view, dns_name_t *name, isc_boolean_t missing,
271*00b67f09SDavid van Moolenbroek        dns_rdata_t *rdata)
272*00b67f09SDavid van Moolenbroek {
273*00b67f09SDavid van Moolenbroek 	const char *viewname = "", *sep = "";
274*00b67f09SDavid van Moolenbroek 	char namebuf[DNS_NAME_FORMATSIZE];
275*00b67f09SDavid van Moolenbroek 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
276*00b67f09SDavid van Moolenbroek 	char databuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
277*00b67f09SDavid van Moolenbroek 	isc_buffer_t buffer;
278*00b67f09SDavid van Moolenbroek 	isc_result_t result;
279*00b67f09SDavid van Moolenbroek 
280*00b67f09SDavid van Moolenbroek 	if (strcmp(view->name, "_bind") != 0 &&
281*00b67f09SDavid van Moolenbroek 	    strcmp(view->name, "_default") != 0) {
282*00b67f09SDavid van Moolenbroek 		viewname = view->name;
283*00b67f09SDavid van Moolenbroek 		sep = ": view ";
284*00b67f09SDavid van Moolenbroek 	}
285*00b67f09SDavid van Moolenbroek 
286*00b67f09SDavid van Moolenbroek 	dns_name_format(name, namebuf, sizeof(namebuf));
287*00b67f09SDavid van Moolenbroek 	dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
288*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&buffer, databuf, sizeof(databuf) - 1);
289*00b67f09SDavid van Moolenbroek 	result = dns_rdata_totext(rdata, NULL, &buffer);
290*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
291*00b67f09SDavid van Moolenbroek 	databuf[isc_buffer_usedlength(&buffer)] = '\0';
292*00b67f09SDavid van Moolenbroek 
293*00b67f09SDavid van Moolenbroek 	if (missing)
294*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
295*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
296*00b67f09SDavid van Moolenbroek 			      "checkhints%s%s: %s/%s (%s) missing from hints",
297*00b67f09SDavid van Moolenbroek 			      sep, viewname, namebuf, typebuf, databuf);
298*00b67f09SDavid van Moolenbroek 	else
299*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
300*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
301*00b67f09SDavid van Moolenbroek 			      "checkhints%s%s: %s/%s (%s) extra record "
302*00b67f09SDavid van Moolenbroek 			      "in hints", sep, viewname, namebuf, typebuf,
303*00b67f09SDavid van Moolenbroek 			      databuf);
304*00b67f09SDavid van Moolenbroek }
305*00b67f09SDavid van Moolenbroek 
306*00b67f09SDavid van Moolenbroek static isc_boolean_t
inrrset(dns_rdataset_t * rrset,dns_rdata_t * rdata)307*00b67f09SDavid van Moolenbroek inrrset(dns_rdataset_t *rrset, dns_rdata_t *rdata) {
308*00b67f09SDavid van Moolenbroek 	isc_result_t result;
309*00b67f09SDavid van Moolenbroek 	dns_rdata_t current = DNS_RDATA_INIT;
310*00b67f09SDavid van Moolenbroek 
311*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(rrset);
312*00b67f09SDavid van Moolenbroek 	while (result == ISC_R_SUCCESS) {
313*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(rrset, &current);
314*00b67f09SDavid van Moolenbroek 		if (dns_rdata_compare(rdata, &current) == 0)
315*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
316*00b67f09SDavid van Moolenbroek 		dns_rdata_reset(&current);
317*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_next(rrset);
318*00b67f09SDavid van Moolenbroek 	}
319*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
320*00b67f09SDavid van Moolenbroek }
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek /*
323*00b67f09SDavid van Moolenbroek  * Check that the address RRsets match.
324*00b67f09SDavid van Moolenbroek  *
325*00b67f09SDavid van Moolenbroek  * Note we don't complain about missing glue records.
326*00b67f09SDavid van Moolenbroek  */
327*00b67f09SDavid van Moolenbroek 
328*00b67f09SDavid van Moolenbroek static void
check_address_records(dns_view_t * view,dns_db_t * hints,dns_db_t * db,dns_name_t * name,isc_stdtime_t now)329*00b67f09SDavid van Moolenbroek check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
330*00b67f09SDavid van Moolenbroek 		      dns_name_t *name, isc_stdtime_t now)
331*00b67f09SDavid van Moolenbroek {
332*00b67f09SDavid van Moolenbroek 	isc_result_t hresult, rresult, result;
333*00b67f09SDavid van Moolenbroek 	dns_rdataset_t hintrrset, rootrrset;
334*00b67f09SDavid van Moolenbroek 	dns_rdata_t rdata = DNS_RDATA_INIT;
335*00b67f09SDavid van Moolenbroek 	dns_name_t *foundname;
336*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
337*00b67f09SDavid van Moolenbroek 
338*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&hintrrset);
339*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&rootrrset);
340*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
341*00b67f09SDavid van Moolenbroek 	foundname = dns_fixedname_name(&fixed);
342*00b67f09SDavid van Moolenbroek 
343*00b67f09SDavid van Moolenbroek 	hresult = dns_db_find(hints, name, NULL, dns_rdatatype_a, 0,
344*00b67f09SDavid van Moolenbroek 			      now, NULL, foundname, &hintrrset, NULL);
345*00b67f09SDavid van Moolenbroek 	rresult = dns_db_find(db, name, NULL, dns_rdatatype_a,
346*00b67f09SDavid van Moolenbroek 			      DNS_DBFIND_GLUEOK, now, NULL, foundname,
347*00b67f09SDavid van Moolenbroek 			      &rootrrset, NULL);
348*00b67f09SDavid van Moolenbroek 	if (hresult == ISC_R_SUCCESS &&
349*00b67f09SDavid van Moolenbroek 	    (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
350*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_first(&rootrrset);
351*00b67f09SDavid van Moolenbroek 		while (result == ISC_R_SUCCESS) {
352*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
353*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(&rootrrset, &rdata);
354*00b67f09SDavid van Moolenbroek 			if (!inrrset(&hintrrset, &rdata))
355*00b67f09SDavid van Moolenbroek 				report(view, name, ISC_TRUE, &rdata);
356*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_next(&rootrrset);
357*00b67f09SDavid van Moolenbroek 		}
358*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_first(&hintrrset);
359*00b67f09SDavid van Moolenbroek 		while (result == ISC_R_SUCCESS) {
360*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
361*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(&hintrrset, &rdata);
362*00b67f09SDavid van Moolenbroek 			if (!inrrset(&rootrrset, &rdata))
363*00b67f09SDavid van Moolenbroek 				report(view, name, ISC_FALSE, &rdata);
364*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_next(&hintrrset);
365*00b67f09SDavid van Moolenbroek 		}
366*00b67f09SDavid van Moolenbroek 	}
367*00b67f09SDavid van Moolenbroek 	if (hresult == ISC_R_NOTFOUND &&
368*00b67f09SDavid van Moolenbroek 	    (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
369*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_first(&rootrrset);
370*00b67f09SDavid van Moolenbroek 		while (result == ISC_R_SUCCESS) {
371*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
372*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(&rootrrset, &rdata);
373*00b67f09SDavid van Moolenbroek 			report(view, name, ISC_TRUE, &rdata);
374*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_next(&rootrrset);
375*00b67f09SDavid van Moolenbroek 		}
376*00b67f09SDavid van Moolenbroek 	}
377*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&rootrrset))
378*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rootrrset);
379*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&hintrrset))
380*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&hintrrset);
381*00b67f09SDavid van Moolenbroek 
382*00b67f09SDavid van Moolenbroek 	/*
383*00b67f09SDavid van Moolenbroek 	 * Check AAAA records.
384*00b67f09SDavid van Moolenbroek 	 */
385*00b67f09SDavid van Moolenbroek 	hresult = dns_db_find(hints, name, NULL, dns_rdatatype_aaaa, 0,
386*00b67f09SDavid van Moolenbroek 			      now, NULL, foundname, &hintrrset, NULL);
387*00b67f09SDavid van Moolenbroek 	rresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
388*00b67f09SDavid van Moolenbroek 			      DNS_DBFIND_GLUEOK, now, NULL, foundname,
389*00b67f09SDavid van Moolenbroek 			      &rootrrset, NULL);
390*00b67f09SDavid van Moolenbroek 	if (hresult == ISC_R_SUCCESS &&
391*00b67f09SDavid van Moolenbroek 	    (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
392*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_first(&rootrrset);
393*00b67f09SDavid van Moolenbroek 		while (result == ISC_R_SUCCESS) {
394*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
395*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(&rootrrset, &rdata);
396*00b67f09SDavid van Moolenbroek 			if (!inrrset(&hintrrset, &rdata))
397*00b67f09SDavid van Moolenbroek 				report(view, name, ISC_TRUE, &rdata);
398*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
399*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_next(&rootrrset);
400*00b67f09SDavid van Moolenbroek 		}
401*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_first(&hintrrset);
402*00b67f09SDavid van Moolenbroek 		while (result == ISC_R_SUCCESS) {
403*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
404*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(&hintrrset, &rdata);
405*00b67f09SDavid van Moolenbroek 			if (!inrrset(&rootrrset, &rdata))
406*00b67f09SDavid van Moolenbroek 				report(view, name, ISC_FALSE, &rdata);
407*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
408*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_next(&hintrrset);
409*00b67f09SDavid van Moolenbroek 		}
410*00b67f09SDavid van Moolenbroek 	}
411*00b67f09SDavid van Moolenbroek 	if (hresult == ISC_R_NOTFOUND &&
412*00b67f09SDavid van Moolenbroek 	    (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
413*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_first(&rootrrset);
414*00b67f09SDavid van Moolenbroek 		while (result == ISC_R_SUCCESS) {
415*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
416*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(&rootrrset, &rdata);
417*00b67f09SDavid van Moolenbroek 			report(view, name, ISC_TRUE, &rdata);
418*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
419*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_next(&rootrrset);
420*00b67f09SDavid van Moolenbroek 		}
421*00b67f09SDavid van Moolenbroek 	}
422*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&rootrrset))
423*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rootrrset);
424*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&hintrrset))
425*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&hintrrset);
426*00b67f09SDavid van Moolenbroek }
427*00b67f09SDavid van Moolenbroek 
428*00b67f09SDavid van Moolenbroek void
dns_root_checkhints(dns_view_t * view,dns_db_t * hints,dns_db_t * db)429*00b67f09SDavid van Moolenbroek dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) {
430*00b67f09SDavid van Moolenbroek 	isc_result_t result;
431*00b67f09SDavid van Moolenbroek 	dns_rdata_t rdata = DNS_RDATA_INIT;
432*00b67f09SDavid van Moolenbroek 	dns_rdata_ns_t ns;
433*00b67f09SDavid van Moolenbroek 	dns_rdataset_t hintns, rootns;
434*00b67f09SDavid van Moolenbroek 	const char *viewname = "", *sep = "";
435*00b67f09SDavid van Moolenbroek 	isc_stdtime_t now;
436*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
437*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
438*00b67f09SDavid van Moolenbroek 
439*00b67f09SDavid van Moolenbroek 	REQUIRE(hints != NULL);
440*00b67f09SDavid van Moolenbroek 	REQUIRE(db != NULL);
441*00b67f09SDavid van Moolenbroek 	REQUIRE(view != NULL);
442*00b67f09SDavid van Moolenbroek 
443*00b67f09SDavid van Moolenbroek 	isc_stdtime_get(&now);
444*00b67f09SDavid van Moolenbroek 
445*00b67f09SDavid van Moolenbroek 	if (strcmp(view->name, "_bind") != 0 &&
446*00b67f09SDavid van Moolenbroek 	    strcmp(view->name, "_default") != 0) {
447*00b67f09SDavid van Moolenbroek 		viewname = view->name;
448*00b67f09SDavid van Moolenbroek 		sep = ": view ";
449*00b67f09SDavid van Moolenbroek 	}
450*00b67f09SDavid van Moolenbroek 
451*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&hintns);
452*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&rootns);
453*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
454*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fixed);
455*00b67f09SDavid van Moolenbroek 
456*00b67f09SDavid van Moolenbroek 	result = dns_db_find(hints, dns_rootname, NULL, dns_rdatatype_ns, 0,
457*00b67f09SDavid van Moolenbroek 			     now, NULL, name, &hintns, NULL);
458*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
459*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
460*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
461*00b67f09SDavid van Moolenbroek 			      "checkhints%s%s: unable to get root NS rrset "
462*00b67f09SDavid van Moolenbroek 			      "from hints: %s", sep, viewname,
463*00b67f09SDavid van Moolenbroek 			      dns_result_totext(result));
464*00b67f09SDavid van Moolenbroek 		goto cleanup;
465*00b67f09SDavid van Moolenbroek 	}
466*00b67f09SDavid van Moolenbroek 
467*00b67f09SDavid van Moolenbroek 	result = dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0,
468*00b67f09SDavid van Moolenbroek 			     now, NULL, name, &rootns, NULL);
469*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
470*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
471*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
472*00b67f09SDavid van Moolenbroek 			      "checkhints%s%s: unable to get root NS rrset "
473*00b67f09SDavid van Moolenbroek 			      "from cache: %s", sep, viewname,
474*00b67f09SDavid van Moolenbroek 			      dns_result_totext(result));
475*00b67f09SDavid van Moolenbroek 		goto cleanup;
476*00b67f09SDavid van Moolenbroek 	}
477*00b67f09SDavid van Moolenbroek 
478*00b67f09SDavid van Moolenbroek 	/*
479*00b67f09SDavid van Moolenbroek 	 * Look for missing root NS names.
480*00b67f09SDavid van Moolenbroek 	 */
481*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(&rootns);
482*00b67f09SDavid van Moolenbroek 	while (result == ISC_R_SUCCESS) {
483*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(&rootns, &rdata);
484*00b67f09SDavid van Moolenbroek 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
485*00b67f09SDavid van Moolenbroek 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
486*00b67f09SDavid van Moolenbroek 		result = in_rootns(&hintns, &ns.name);
487*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
488*00b67f09SDavid van Moolenbroek 			char namebuf[DNS_NAME_FORMATSIZE];
489*00b67f09SDavid van Moolenbroek 			/* missing from hints */
490*00b67f09SDavid van Moolenbroek 			dns_name_format(&ns.name, namebuf, sizeof(namebuf));
491*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
492*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
493*00b67f09SDavid van Moolenbroek 				      "checkhints%s%s: unable to find root "
494*00b67f09SDavid van Moolenbroek 				      "NS '%s' in hints", sep, viewname,
495*00b67f09SDavid van Moolenbroek 				      namebuf);
496*00b67f09SDavid van Moolenbroek 		} else
497*00b67f09SDavid van Moolenbroek 			check_address_records(view, hints, db, &ns.name, now);
498*00b67f09SDavid van Moolenbroek 		dns_rdata_reset(&rdata);
499*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_next(&rootns);
500*00b67f09SDavid van Moolenbroek 	}
501*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_NOMORE) {
502*00b67f09SDavid van Moolenbroek 		goto cleanup;
503*00b67f09SDavid van Moolenbroek 	}
504*00b67f09SDavid van Moolenbroek 
505*00b67f09SDavid van Moolenbroek 	/*
506*00b67f09SDavid van Moolenbroek 	 * Look for extra root NS names.
507*00b67f09SDavid van Moolenbroek 	 */
508*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(&hintns);
509*00b67f09SDavid van Moolenbroek 	while (result == ISC_R_SUCCESS) {
510*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(&hintns, &rdata);
511*00b67f09SDavid van Moolenbroek 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
512*00b67f09SDavid van Moolenbroek 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
513*00b67f09SDavid van Moolenbroek 		result = in_rootns(&rootns, &ns.name);
514*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
515*00b67f09SDavid van Moolenbroek 			char namebuf[DNS_NAME_FORMATSIZE];
516*00b67f09SDavid van Moolenbroek 			/* extra entry in hints */
517*00b67f09SDavid van Moolenbroek 			dns_name_format(&ns.name, namebuf, sizeof(namebuf));
518*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
519*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
520*00b67f09SDavid van Moolenbroek 				      "checkhints%s%s: extra NS '%s' in hints",
521*00b67f09SDavid van Moolenbroek 				      sep, viewname, namebuf);
522*00b67f09SDavid van Moolenbroek 		}
523*00b67f09SDavid van Moolenbroek 		dns_rdata_reset(&rdata);
524*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_next(&hintns);
525*00b67f09SDavid van Moolenbroek 	}
526*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_NOMORE) {
527*00b67f09SDavid van Moolenbroek 		goto cleanup;
528*00b67f09SDavid van Moolenbroek 	}
529*00b67f09SDavid van Moolenbroek 
530*00b67f09SDavid van Moolenbroek  cleanup:
531*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&rootns))
532*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rootns);
533*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&hintns))
534*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&hintns);
535*00b67f09SDavid van Moolenbroek }
536