]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1801. [func] Report differences between hints and real NS rrset
authorMark Andrews <marka@isc.org>
Mon, 7 Feb 2005 00:53:29 +0000 (00:53 +0000)
committerMark Andrews <marka@isc.org>
Mon, 7 Feb 2005 00:53:29 +0000 (00:53 +0000)
                        and associated address records.

CHANGES
lib/dns/include/dns/rootns.h
lib/dns/resolver.c
lib/dns/rootns.c

diff --git a/CHANGES b/CHANGES
index 4e628031ec75c4c5da02b9a6f7c0307e97f74a6b..9ed87b3140a57b7e098ab5a22277d23fe8128bda 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -15,7 +15,8 @@
 
 1802.  [placeholder]   rt11280
 
-1801.  [placeholder]   rt288
+1801.  [func]          Report differences between hints and real NS rrset
+                       and associated address records.
 
 1800.  [bug]           Changes #1719 allowed a INSIST to be triggered.
                        [RT #13428]
index 0b10c7796860f0e7004837d97d6b5ffb02f2bdeb..ab95d1609992878114a5cca0b0c71af8ea51b680 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rootns.h,v 1.9 2004/03/05 05:09:46 marka Exp $ */
+/* $Id: rootns.h,v 1.10 2005/02/07 00:53:29 marka Exp $ */
 
 #ifndef DNS_ROOTNS_H
 #define DNS_ROOTNS_H 1
@@ -30,6 +30,14 @@ isc_result_t
 dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
                   const char *filename, dns_db_t **target);
 
+void
+dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db);
+/*
+ * Reports differences between hints and the real roots.
+ *
+ * Requires view, hints and (cache) db to be valid.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_ROOTNS_H */
index 5128c96de9262116ecf3465933801a735d99e17d..cbb2cee73e87cff5ee01fe5882a98852d33b89e3 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.301 2005/01/20 00:01:46 marka Exp $ */
+/* $Id: resolver.c,v 1.302 2005/02/07 00:53:28 marka Exp $ */
 
 #include <config.h>
 
@@ -27,6 +27,7 @@
 
 #include <dns/acl.h>
 #include <dns/adb.h>
+#include <dns/cache.h>
 #include <dns/db.h>
 #include <dns/dispatch.h>
 #include <dns/events.h>
@@ -47,6 +48,7 @@
 #include <dns/rdatatype.h>
 #include <dns/resolver.h>
 #include <dns/result.h>
+#include <dns/rootns.h>
 #include <dns/tsig.h>
 #include <dns/validator.h>
 
@@ -5814,6 +5816,7 @@ prime_done(isc_task_t *task, isc_event_t *event) {
        dns_resolver_t *res;
        dns_fetchevent_t *fevent;
        dns_fetch_t *fetch;
+       dns_db_t *db = NULL;
 
        REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
        fevent = (dns_fetchevent_t *)event;
@@ -5832,6 +5835,13 @@ prime_done(isc_task_t *task, isc_event_t *event) {
        UNLOCK(&res->primelock);
 
        UNLOCK(&res->lock);
+       
+       if (fevent->result == ISC_R_SUCCESS &&
+           res->view->cache != NULL && res->view->hints != NULL) {
+               dns_cache_attachdb(res->view->cache, &db);
+               dns_root_checkhints(res->view, res->view->hints, db);
+               dns_db_detach(&db);
+       }
 
        if (fevent->node != NULL)
                dns_db_detachnode(fevent->db, &fevent->node);
index 36f764eddbf8e6483a39343c56d439765aedbc34..6acb1c95bcdaf8f9017d67687d947fb949f628d3 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rootns.c,v 1.26 2004/03/05 05:09:24 marka Exp $ */
+/* $Id: rootns.c,v 1.27 2005/02/07 00:53:29 marka Exp $ */
 
 #include <config.h>
 
 #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 +248,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, &current);
+               if (dns_rdata_compare(rdata, &current) == 0)
+                       return (ISC_TRUE);
+               dns_rdata_reset(&current);
+               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);
+}