summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/bin/check/check-tool.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/bin/check/check-tool.c')
-rw-r--r--contrib/bind9/bin/check/check-tool.c380
1 files changed, 367 insertions, 13 deletions
diff --git a/contrib/bind9/bin/check/check-tool.c b/contrib/bind9/bin/check/check-tool.c
index 1b67ca8..c8ef4df 100644
--- a/contrib/bind9/bin/check/check-tool.c
+++ b/contrib/bind9/bin/check/check-tool.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: check-tool.c,v 1.4.12.7 2004/11/30 01:15:40 marka Exp $ */
+/* $Id: check-tool.c,v 1.10.18.14 2006/06/08 01:43:00 marka Exp $ */
+
+/*! \file */
#include <config.h>
@@ -27,6 +29,8 @@
#include <isc/buffer.h>
#include <isc/log.h>
+#include <isc/net.h>
+#include <isc/netdb.h>
#include <isc/region.h>
#include <isc/stdio.h>
#include <isc/types.h>
@@ -34,24 +38,360 @@
#include <dns/fixedname.h>
#include <dns/log.h>
#include <dns/name.h>
+#include <dns/rdata.h>
#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
#include <dns/types.h>
#include <dns/zone.h>
+#include <isccfg/log.h>
+
+#ifdef HAVE_ADDRINFO
+#ifdef HAVE_GETADDRINFO
+#ifdef HAVE_GAISTRERROR
+#define USE_GETADDRINFO
+#endif
+#endif
+#endif
+
#define CHECK(r) \
- do { \
+ do { \
result = (r); \
- if (result != ISC_R_SUCCESS) \
- goto cleanup; \
- } while (0)
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
static const char *dbtype[] = { "rbt" };
int debug = 0;
isc_boolean_t nomerge = ISC_TRUE;
+isc_boolean_t docheckmx = ISC_TRUE;
+isc_boolean_t dochecksrv = ISC_TRUE;
+isc_boolean_t docheckns = ISC_TRUE;
unsigned int zone_options = DNS_ZONEOPT_CHECKNS |
+ DNS_ZONEOPT_CHECKMX |
DNS_ZONEOPT_MANYERRORS |
- DNS_ZONEOPT_CHECKNAMES;
+ DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKINTEGRITY |
+ DNS_ZONEOPT_CHECKWILDCARD |
+ DNS_ZONEOPT_WARNMXCNAME |
+ DNS_ZONEOPT_WARNSRVCNAME;
+
+/*
+ * This needs to match the list in bin/named/log.c.
+ */
+static isc_logcategory_t categories[] = {
+ { "", 0 },
+ { "client", 0 },
+ { "network", 0 },
+ { "update", 0 },
+ { "queries", 0 },
+ { "unmatched", 0 },
+ { "update-security", 0 },
+ { NULL, 0 }
+};
+
+static isc_boolean_t
+checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner,
+ dns_rdataset_t *a, dns_rdataset_t *aaaa)
+{
+#ifdef USE_GETADDRINFO
+ dns_rdataset_t *rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ struct addrinfo hints, *ai, *cur;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
+ isc_boolean_t answer = ISC_TRUE;
+ isc_boolean_t match;
+ const char *type;
+ void *ptr = NULL;
+ int result;
+
+ REQUIRE(a == NULL || !dns_rdataset_isassociated(a) ||
+ a->type == dns_rdatatype_a);
+ REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) ||
+ aaaa->type == dns_rdatatype_aaaa);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U)
+ strcat(namebuf, ".");
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ if (strcasecmp(ai->ai_canonname, namebuf) != 0) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/NS '%s' (out of zone) "
+ "is a CNAME (illegal)",
+ ownerbuf, namebuf);
+ /* XXX950 make fatal for 9.5.0 */
+ /* answer = ISC_FALSE; */
+ }
+ break;
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ /* XXX950 make fatal for 9.5.0 */
+ return (ISC_TRUE);
+
+ default:
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s",
+ namebuf, gai_strerror(result));
+ return (ISC_TRUE);
+ }
+ if (a == NULL || aaaa == NULL)
+ return (answer);
+ /*
+ * Check that all glue records really exist.
+ */
+ if (!dns_rdataset_isassociated(a))
+ goto checkaaaa;
+ result = dns_rdataset_first(a);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(a, &rdata);
+ match = ISC_FALSE;
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET)
+ continue;
+ ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
+ if (memcmp(ptr, rdata.data, rdata.length) == 0) {
+ match = ISC_TRUE;
+ break;
+ }
+ }
+ if (!match) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
+ "extra GLUE A record (%s)",
+ ownerbuf, namebuf,
+ inet_ntop(AF_INET, rdata.data,
+ addrbuf, sizeof(addrbuf)));
+ /* XXX950 make fatal for 9.5.0 */
+ /* answer = ISC_FALSE; */
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(a);
+ }
+
+ checkaaaa:
+ if (!dns_rdataset_isassociated(aaaa))
+ goto checkmissing;
+ result = dns_rdataset_first(aaaa);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(aaaa, &rdata);
+ match = ISC_FALSE;
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET6)
+ continue;
+ ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
+ if (memcmp(ptr, rdata.data, rdata.length) == 0) {
+ match = ISC_TRUE;
+ break;
+ }
+ }
+ if (!match) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
+ "extra GLUE AAAA record (%s)",
+ ownerbuf, namebuf,
+ inet_ntop(AF_INET6, rdata.data,
+ addrbuf, sizeof(addrbuf)));
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = ISC_FALSE; */
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(aaaa);
+ }
+
+ checkmissing:
+ /*
+ * Check that all addresses appear in the glue.
+ */
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ switch (cur->ai_family) {
+ case AF_INET:
+ rdataset = a;
+ ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
+ type = "A";
+ break;
+ case AF_INET6:
+ rdataset = aaaa;
+ ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
+ type = "AAAA";
+ break;
+ default:
+ continue;
+ }
+ match = ISC_FALSE;
+ if (dns_rdataset_isassociated(rdataset))
+ result = dns_rdataset_first(rdataset);
+ else
+ result = ISC_R_FAILURE;
+ while (result == ISC_R_SUCCESS && !match) {
+ dns_rdataset_current(rdataset, &rdata);
+ if (memcmp(ptr, rdata.data, rdata.length) == 0)
+ match = ISC_TRUE;
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(rdataset);
+ }
+ if (!match) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
+ "missing GLUE %s record (%s)",
+ ownerbuf, namebuf, type,
+ inet_ntop(cur->ai_family, ptr,
+ addrbuf, sizeof(addrbuf)));
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = ISC_FALSE; */
+ }
+ }
+ freeaddrinfo(ai);
+ return (answer);
+#else
+ return (ISC_TRUE);
+#endif
+}
+
+static isc_boolean_t
+checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
+#ifdef USE_GETADDRINFO
+ struct addrinfo hints, *ai;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ int result;
+ int level = ISC_LOG_ERROR;
+ isc_boolean_t answer = ISC_TRUE;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U)
+ strcat(namebuf, ".");
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ if (strcasecmp(ai->ai_canonname, namebuf) != 0) {
+ if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0)
+ level = ISC_LOG_WARNING;
+ if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "%s/MX '%s' (out of zone) "
+ "is a CNAME (illegal)",
+ ownerbuf, namebuf);
+ if (level == ISC_LOG_ERROR)
+ answer = ISC_FALSE;
+ }
+ }
+ freeaddrinfo(ai);
+ return (answer);
+
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/MX '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ /* XXX950 make fatal for 9.5.0. */
+ return (ISC_TRUE);
+
+ default:
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s",
+ namebuf, gai_strerror(result));
+ return (ISC_TRUE);
+ }
+#else
+ return (ISC_TRUE);
+#endif
+}
+
+static isc_boolean_t
+checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
+#ifdef USE_GETADDRINFO
+ struct addrinfo hints, *ai;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ int result;
+ int level = ISC_LOG_ERROR;
+ isc_boolean_t answer = ISC_TRUE;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U)
+ strcat(namebuf, ".");
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ if (strcasecmp(ai->ai_canonname, namebuf) != 0) {
+ if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0)
+ level = ISC_LOG_WARNING;
+ if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
+ dns_zone_log(zone, level,
+ "%s/SRV '%s' (out of zone) "
+ "is a CNAME (illegal)",
+ ownerbuf, namebuf);
+ if (level == ISC_LOG_ERROR)
+ answer = ISC_FALSE;
+ }
+ }
+ freeaddrinfo(ai);
+ return (answer);
+
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/SRV '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ /* XXX950 make fatal for 9.5.0. */
+ return (ISC_TRUE);
+
+ default:
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s",
+ namebuf, gai_strerror(result));
+ return (ISC_TRUE);
+ }
+#else
+ return (ISC_TRUE);
+#endif
+}
isc_result_t
setup_logging(isc_mem_t *mctx, isc_log_t **logp) {
@@ -60,7 +400,11 @@ setup_logging(isc_mem_t *mctx, isc_log_t **logp) {
isc_log_t *log = NULL;
RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
+ isc_log_registercategories(log, categories);
isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+ cfg_log_init(log);
destination.file.stream = stdout;
destination.file.name = NULL;
@@ -77,9 +421,11 @@ setup_logging(isc_mem_t *mctx, isc_log_t **logp) {
return (ISC_R_SUCCESS);
}
+/*% load the zone */
isc_result_t
load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
- const char *classname, dns_zone_t **zonep)
+ dns_masterformat_t fileformat, const char *classname,
+ dns_zone_t **zonep)
{
isc_result_t result;
dns_rdataclass_t rdclass;
@@ -104,10 +450,10 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
dns_fixedname_init(&fixorigin);
origin = dns_fixedname_name(&fixorigin);
CHECK(dns_name_fromtext(origin, &buffer, dns_rootname,
- ISC_FALSE, NULL));
+ ISC_FALSE, NULL));
CHECK(dns_zone_setorigin(zone, origin));
CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
- CHECK(dns_zone_setfile(zone, filename));
+ CHECK(dns_zone_setfile2(zone, filename, fileformat));
DE_CONST(classname, region.base);
region.length = strlen(classname);
@@ -116,9 +462,15 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
dns_zone_setclass(zone, rdclass);
dns_zone_setoption(zone, zone_options, ISC_TRUE);
dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
+ if (docheckmx)
+ dns_zone_setcheckmx(zone, checkmx);
+ if (docheckns)
+ dns_zone_setcheckns(zone, checkns);
+ if (dochecksrv)
+ dns_zone_setchecksrv(zone, checksrv);
CHECK(dns_zone_load(zone));
- if (zonep != NULL){
+ if (zonep != NULL) {
*zonep = zone;
zone = NULL;
}
@@ -129,8 +481,10 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
return (result);
}
+/*% dump the zone */
isc_result_t
-dump_zone(const char *zonename, dns_zone_t *zone, const char *filename)
+dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
+ dns_masterformat_t fileformat, const dns_master_style_t *style)
{
isc_result_t result;
FILE *output = stdout;
@@ -153,7 +507,7 @@ dump_zone(const char *zonename, dns_zone_t *zone, const char *filename)
}
}
- result = dns_zone_fulldumptostream(zone, output);
+ result = dns_zone_dumptostream2(zone, output, fileformat, style);
if (filename != NULL)
(void)isc_stdio_close(output);
OpenPOWER on IntegriCloud