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