diff options
Diffstat (limited to 'contrib/bind9/lib/dns/rootns.c')
-rw-r--r-- | contrib/bind9/lib/dns/rootns.c | 275 |
1 files changed, 271 insertions, 4 deletions
diff --git a/contrib/bind9/lib/dns/rootns.c b/contrib/bind9/lib/dns/rootns.c index 9e9c940..1c038a4 100644 --- a/contrib/bind9/lib/dns/rootns.c +++ b/contrib/bind9/lib/dns/rootns.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rootns.c,v 1.20.2.3.2.5 2004/03/08 09:04:32 marka Exp $ */ +/* $Id: rootns.c,v 1.26.18.3 2005/04/27 05:01:26 sra Exp $ */ + +/*! \file */ #include <config.h> @@ -26,15 +28,18 @@ #include <dns/callbacks.h> #include <dns/db.h> #include <dns/dbiterator.h> -#include <dns/log.h> #include <dns/fixedname.h> +#include <dns/log.h> #include <dns/master.h> #include <dns/rdata.h> -#include <dns/rdatasetiter.h> +#include <dns/rdata.h> #include <dns/rdataset.h> +#include <dns/rdatasetiter.h> #include <dns/rdatastruct.h> +#include <dns/rdatatype.h> #include <dns/result.h> #include <dns/rootns.h> +#include <dns/view.h> static char root_ns[] = ";\n" @@ -245,3 +250,265 @@ dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, return (result); } + +static void +report(dns_view_t *view, dns_name_t *name, isc_boolean_t missing, + dns_rdata_t *rdata) +{ + const char *viewname = "", *sep = ""; + char namebuf[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + char databuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")]; + isc_buffer_t buffer; + isc_result_t result; + + if (strcmp(view->name, "_bind") != 0 && + strcmp(view->name, "_default") != 0) { + viewname = view->name; + sep = ": view "; + } + + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf)); + isc_buffer_init(&buffer, databuf, sizeof(databuf) - 1); + result = dns_rdata_totext(rdata, NULL, &buffer); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + databuf[isc_buffer_usedlength(&buffer)] = '\0'; + + if (missing) + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_HINTS, ISC_LOG_WARNING, + "checkhints%s%s: %s/%s (%s) missing from hints", + sep, viewname, namebuf, typebuf, databuf); + else + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_HINTS, ISC_LOG_WARNING, + "checkhints%s%s: %s/%s (%s) extra record " + "in hints", sep, viewname, namebuf, typebuf, + databuf); +} + +static isc_boolean_t +inrrset(dns_rdataset_t *rrset, dns_rdata_t *rdata) { + isc_result_t result; + dns_rdata_t current = DNS_RDATA_INIT; + + result = dns_rdataset_first(rrset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(rrset, ¤t); + if (dns_rdata_compare(rdata, ¤t) == 0) + return (ISC_TRUE); + dns_rdata_reset(¤t); + result = dns_rdataset_next(rrset); + } + return (ISC_FALSE); +} + +/* + * Check that the address RRsets match. + * + * Note we don't complain about missing glue records. + */ + +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) +{ + isc_result_t hresult, rresult, result; + dns_rdataset_t hintrrset, rootrrset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_name_t *foundname; + dns_fixedname_t fixed; + + dns_rdataset_init(&hintrrset); + dns_rdataset_init(&rootrrset); + dns_fixedname_init(&fixed); + foundname = dns_fixedname_name(&fixed); + + hresult = dns_db_find(hints, name, NULL, dns_rdatatype_a, 0, + now, NULL, foundname, &hintrrset, NULL); + rresult = dns_db_find(db, name, NULL, dns_rdatatype_a, + DNS_DBFIND_GLUEOK, now, NULL, foundname, + &rootrrset, NULL); + if (hresult == ISC_R_SUCCESS && + (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) { + result = dns_rdataset_first(&rootrrset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&rootrrset, &rdata); + if (!inrrset(&hintrrset, &rdata)) + report(view, name, ISC_TRUE, &rdata); + result = dns_rdataset_next(&rootrrset); + } + result = dns_rdataset_first(&hintrrset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&hintrrset, &rdata); + if (!inrrset(&rootrrset, &rdata)) + report(view, name, ISC_FALSE, &rdata); + result = dns_rdataset_next(&hintrrset); + } + } + if (hresult == ISC_R_NOTFOUND && + (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) { + result = dns_rdataset_first(&rootrrset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&rootrrset, &rdata); + report(view, name, ISC_TRUE, &rdata); + result = dns_rdataset_next(&rootrrset); + } + } + if (dns_rdataset_isassociated(&rootrrset)) + dns_rdataset_disassociate(&rootrrset); + if (dns_rdataset_isassociated(&hintrrset)) + dns_rdataset_disassociate(&hintrrset); + + /* + * Check AAAA records. + */ + hresult = dns_db_find(hints, name, NULL, dns_rdatatype_aaaa, 0, + now, NULL, foundname, &hintrrset, NULL); + rresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, + DNS_DBFIND_GLUEOK, now, NULL, foundname, + &rootrrset, NULL); + if (hresult == ISC_R_SUCCESS && + (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) { + result = dns_rdataset_first(&rootrrset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&rootrrset, &rdata); + if (!inrrset(&hintrrset, &rdata)) + report(view, name, ISC_TRUE, &rdata); + dns_rdata_reset(&rdata); + result = dns_rdataset_next(&rootrrset); + } + result = dns_rdataset_first(&hintrrset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&hintrrset, &rdata); + if (!inrrset(&rootrrset, &rdata)) + report(view, name, ISC_FALSE, &rdata); + dns_rdata_reset(&rdata); + result = dns_rdataset_next(&hintrrset); + } + } + if (hresult == ISC_R_NOTFOUND && + (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) { + result = dns_rdataset_first(&rootrrset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&rootrrset, &rdata); + report(view, name, ISC_TRUE, &rdata); + dns_rdata_reset(&rdata); + result = dns_rdataset_next(&rootrrset); + } + } + if (dns_rdataset_isassociated(&rootrrset)) + dns_rdataset_disassociate(&rootrrset); + if (dns_rdataset_isassociated(&hintrrset)) + dns_rdataset_disassociate(&hintrrset); +} + +void +dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) { + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_ns_t ns; + dns_rdataset_t hintns, rootns; + const char *viewname = "", *sep = ""; + isc_stdtime_t now; + dns_name_t *name; + dns_fixedname_t fixed; + + REQUIRE(hints != NULL); + REQUIRE(db != NULL); + REQUIRE(view != NULL); + + isc_stdtime_get(&now); + + if (strcmp(view->name, "_bind") != 0 && + strcmp(view->name, "_default") != 0) { + viewname = view->name; + sep = ": view "; + } + + dns_rdataset_init(&hintns); + dns_rdataset_init(&rootns); + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + + result = dns_db_find(hints, dns_rootname, NULL, dns_rdatatype_ns, 0, + now, NULL, name, &hintns, NULL); + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_HINTS, ISC_LOG_WARNING, + "checkhints%s%s: unable to get root NS rrset " + "from hints: %s", sep, viewname, + dns_result_totext(result)); + goto cleanup; + } + + result = dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0, + now, NULL, name, &rootns, NULL); + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_HINTS, ISC_LOG_WARNING, + "checkhints%s%s: unable to get root NS rrset " + "from cache: %s", sep, viewname, + dns_result_totext(result)); + goto cleanup; + } + + /* + * Look for missing root NS names. + */ + result = dns_rdataset_first(&rootns); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&rootns, &rdata); + result = dns_rdata_tostruct(&rdata, &ns, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + result = in_rootns(&hintns, &ns.name); + if (result != ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + /* missing from hints */ + dns_name_format(&ns.name, namebuf, sizeof(namebuf)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_HINTS, ISC_LOG_WARNING, + "checkhints%s%s: unable to find root " + "NS '%s' in hints", sep, viewname, + namebuf); + } else + check_address_records(view, hints, db, &ns.name, now); + dns_rdata_reset(&rdata); + result = dns_rdataset_next(&rootns); + } + if (result != ISC_R_NOMORE) { + goto cleanup; + } + + /* + * Look for extra root NS names. + */ + result = dns_rdataset_first(&hintns); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&hintns, &rdata); + result = dns_rdata_tostruct(&rdata, &ns, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + result = in_rootns(&rootns, &ns.name); + if (result != ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + /* extra entry in hints */ + dns_name_format(&ns.name, namebuf, sizeof(namebuf)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_HINTS, ISC_LOG_WARNING, + "checkhints%s%s: extra NS '%s' in hints", + sep, viewname, namebuf); + } + dns_rdata_reset(&rdata); + result = dns_rdataset_next(&hintns); + } + if (result != ISC_R_NOMORE) { + goto cleanup; + } + + cleanup: + if (dns_rdataset_isassociated(&rootns)) + dns_rdataset_disassociate(&rootns); + if (dns_rdataset_isassociated(&hintns)) + dns_rdataset_disassociate(&hintns); +} |