diff options
Diffstat (limited to '')
88 files changed, 24121 insertions, 0 deletions
diff --git a/lib/dns/tests/Atffile b/lib/dns/tests/Atffile new file mode 100644 index 0000000..953082d --- /dev/null +++ b/lib/dns/tests/Atffile @@ -0,0 +1,34 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = bind9 + +tp: acl_test +tp: db_test +tp: dbdiff_test +tp: dbiterator_test +tp: dbversion_test +tp: dh_test +tp: dispatch_test +tp: dnstap_test +tp: dst_test +tp: geoip_test +tp: gost_test +tp: keytable_test +tp: master_test +tp: name_test +tp: nsec3_test +tp: peer_test +tp: private_test +tp: rbt_serialize_test +tp: rbt_test +tp: rdata_test +tp: rdataset_test +tp: rdatasetstats_test +tp: resolver_test +tp: rsa_test +tp: sigs_test +tp: time_test +tp: tsig_test +tp: update_test +tp: zonemgr_test +tp: zt_test diff --git a/lib/dns/tests/Kdh.+002+18602.key b/lib/dns/tests/Kdh.+002+18602.key new file mode 100644 index 0000000..09b4cf5 --- /dev/null +++ b/lib/dns/tests/Kdh.+002+18602.key @@ -0,0 +1 @@ +dh. IN KEY 0 2 2 AAEBAAAAYIHI/wjtOagNga9GILSoS02IVelgLilPE/TfhtvShsiDAXqb IfxQcj2JkuOnNLs5ttb2WZXWl5/jsSjIxHMwMF2XY4gwt/lwHBf/vgYH r7aIxnKXov1jk9rymTLHGKIOtg== diff --git a/lib/dns/tests/Krsa.+005+29235.key b/lib/dns/tests/Krsa.+005+29235.key new file mode 100644 index 0000000..e2d81e7 --- /dev/null +++ b/lib/dns/tests/Krsa.+005+29235.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 29235, for rsa. +; Created: 20160819191802 (Fri Aug 19 21:18:02 2016) +; Publish: 20160819191802 (Fri Aug 19 21:18:02 2016) +; Activate: 20160819191802 (Fri Aug 19 21:18:02 2016) +rsa. IN DNSKEY 256 3 5 AwEAAdLT1R3qiqCqll3Xzh2qFMvehQ9FODsPftw5U4UjB3QwnJ/3+dph 9kZBBeaJagUBVYzoArk6XNydpp3HhSCFDcIiepL6r8XAifW3SqI1KCne OD38kSCl/Qm9P0+3CFWokGVubsSQ+3dpQZxqx5bzOXthbuzAr6X+gDUE LAyHtCQNmJ+4ktdCoj3DNYW0z/xLvrcB2Lns7H+/qWnGPL4f3hr7Vbak Oeay+4J4KGdY2LFxJUVts6QrgAA8gz4mV9YIJFP+C4B3b/Z7qgqZRxmT 0pic+fJC5+sq0l8KwavPn0n+HqVuJNvppVKMdTbsmmuk69RFGMjbFkP7 tnCiqC9Zi6s= diff --git a/lib/dns/tests/Kyuafile b/lib/dns/tests/Kyuafile new file mode 100644 index 0000000..0353a73 --- /dev/null +++ b/lib/dns/tests/Kyuafile @@ -0,0 +1,33 @@ +syntax(2) +test_suite('bind9') + +atf_test_program{name='acl_test'} +atf_test_program{name='db_test'} +atf_test_program{name='dbdiff_test'} +atf_test_program{name='dbiterator_test'} +atf_test_program{name='dbversion_test'} +atf_test_program{name='dh_test'} +atf_test_program{name='dispatch_test'} +atf_test_program{name='dnstap_test'} +atf_test_program{name='dst_test'} +atf_test_program{name='geoip_test'} +atf_test_program{name='gost_test'} +atf_test_program{name='keytable_test'} +atf_test_program{name='master_test'} +atf_test_program{name='name_test'} +atf_test_program{name='nsec3_test'} +atf_test_program{name='peer_test'} +atf_test_program{name='private_test'} +atf_test_program{name='rbt_serialize_test', is_exclusive=true} +atf_test_program{name='rbt_test'} +atf_test_program{name='rdata_test'} +atf_test_program{name='rdataset_test'} +atf_test_program{name='rdatasetstats_test'} +atf_test_program{name='resolver_test'} +atf_test_program{name='rsa_test'} +atf_test_program{name='sigs_test'} +atf_test_program{name='time_test'} +atf_test_program{name='tsig_test'} +atf_test_program{name='update_test'} +atf_test_program{name='zonemgr_test'} +atf_test_program{name='zt_test'} diff --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in new file mode 100644 index 0000000..58fa872 --- /dev/null +++ b/lib/dns/tests/Makefile.in @@ -0,0 +1,266 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +# Attempt to disable parallel processing. +.NOTPARALLEL: +.NO_PARALLEL: + +VERSION=@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} \ + @DST_OPENSSL_INC@ +CDEFINES = @CRYPTO@ -DTESTS="\"${top_builddir}/lib/dns/tests/\"" + +ISCLIBS = ../../isc/libisc.@A@ +ISCDEPLIBS = ../../isc/libisc.@A@ +DNSLIBS = ../libdns.@A@ @DNS_CRYPTO_LIBS@ +DNSDEPLIBS = ../libdns.@A@ + +LIBS = @LIBS@ @ATFLIBS@ + +OBJS = dnstest.@O@ +SRCS = acl_test.c \ + db_test.c \ + dbdiff_test.c \ + dbiterator_test.c \ + dh_test.c \ + dispatch_test.c \ + dnstap_test.c \ + dst_test.c \ + dnstest.c \ + geoip_test.c \ + gost_test.c \ + keytable_test.c \ + master_test.c \ + name_test.c \ + nsec3_test.c \ + peer_test.c \ + private_test.c \ + rbt_test.c \ + rbt_serialize_test.c \ + rdata_test.c \ + rdataset_test.c \ + rdatasetstats_test.c \ + resolver_test.c \ + rsa_test.c \ + sigs_test.c \ + time_test.c \ + tsig_test.c \ + update_test.c \ + zonemgr_test.c \ + zt_test.c + +SUBDIRS = +TARGETS = acl_test@EXEEXT@ \ + db_test@EXEEXT@ \ + dbdiff_test@EXEEXT@ \ + dbiterator_test@EXEEXT@ \ + dbversion_test@EXEEXT@ \ + dh_test@EXEEXT@ \ + dispatch_test@EXEEXT@ \ + dnstap_test@EXEEXT@ \ + dst_test@EXEEXT@ \ + geoip_test@EXEEXT@ \ + gost_test@EXEEXT@ \ + keytable_test@EXEEXT@ \ + master_test@EXEEXT@ \ + name_test@EXEEXT@ \ + nsec3_test@EXEEXT@ \ + peer_test@EXEEXT@ \ + private_test@EXEEXT@ \ + rbt_test@EXEEXT@ \ + rbt_serialize_test@EXEEXT@ \ + rdata_test@EXEEXT@ \ + rdataset_test@EXEEXT@ \ + rdatasetstats_test@EXEEXT@ \ + resolver_test@EXEEXT@ \ + rsa_test@EXEEXT@ \ + sigs_test@EXEEXT@ \ + time_test@EXEEXT@ \ + tsig_test@EXEEXT@ \ + update_test@EXEEXT@ \ + zonemgr_test@EXEEXT@ \ + zt_test@EXEEXT@ + +@BIND9_MAKE_RULES@ + +acl_test@EXEEXT@: acl_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + acl_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +master_test@EXEEXT@: master_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + test -d testdata || mkdir testdata + test -d testdata/master || mkdir testdata/master + ${PERL} ${srcdir}/mkraw.pl < ${srcdir}/testdata/master/master12.data.in \ + > testdata/master/master12.data + ${PERL} ${srcdir}/mkraw.pl < ${srcdir}/testdata/master/master13.data.in \ + > testdata/master/master13.data + ${PERL} ${srcdir}/mkraw.pl < ${srcdir}/testdata/master/master14.data.in \ + > testdata/master/master14.data + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + master_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +keytable_test@EXEEXT@: keytable_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + keytable_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +time_test@EXEEXT@: time_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + time_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +peer_test@EXEEXT@: peer_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + peer_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +private_test@EXEEXT@: private_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + private_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +update_test@EXEEXT@: update_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + update_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +zonemgr_test@EXEEXT@: zonemgr_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + zonemgr_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +dbiterator_test@EXEEXT@: dbiterator_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dbiterator_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +dbdiff_test@EXEEXT@: dbdiff_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dbdiff_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +dbversion_test@EXEEXT@: dbversion_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dbversion_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +zt_test@EXEEXT@: zt_test.@O@ dnstest.@O@ \ + ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + zt_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +name_test@EXEEXT@: name_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + name_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +nsec3_test@EXEEXT@: nsec3_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + nsec3_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +rdataset_test@EXEEXT@: rdataset_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + rdataset_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +dispatch_test@EXEEXT@: dispatch_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dispatch_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +dnstap_test@EXEEXT@: dnstap_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dnstap_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +rdatasetstats_test@EXEEXT@: rdatasetstats_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + rdatasetstats_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +rbt_test@EXEEXT@: rbt_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + rbt_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +rbt_serialize_test@EXEEXT@: rbt_serialize_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + rbt_serialize_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +resolver_test@EXEEXT@: resolver_test.@O@ dnstest.@O@ \ + ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + resolver_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +rdata_test@EXEEXT@: rdata_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + rdata_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +geoip_test@EXEEXT@: geoip_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + geoip_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} +sigs_test@EXEEXT@: sigs_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sigs_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +db_test@EXEEXT@: db_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + db_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +gost_test@EXEEXT@: gost_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + gost_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +dh_test@EXEEXT@: dh_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dh_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +dst_test@EXEEXT@: dst_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dst_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +rsa_test@EXEEXT@: rsa_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + rsa_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +tsig_test@EXEEXT@: tsig_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + tsig_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + +unit:: + sh ${top_builddir}/unit/unittest.sh + +clean distclean:: + rm -f ${TARGETS} + rm -f atf.out + rm -f testdata/master/master12.data testdata/master/master13.data \ + testdata/master/master14.data + rm -f zone.bin diff --git a/lib/dns/tests/acl_test.c b/lib/dns/tests/acl_test.c new file mode 100644 index 0000000..285a990 --- /dev/null +++ b/lib/dns/tests/acl_test.c @@ -0,0 +1,374 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdio.h> +#include <stdbool.h> +#include <unistd.h> + +#include <isc/print.h> +#include <isc/string.h> + +#include <dns/acl.h> +#include "dnstest.h" + +/* + * Helper functions + */ + +#define BUFLEN 255 +#define BIGBUFLEN (70 * 1024) +#define TEST_ORIGIN "test" + +ATF_TC(dns_acl_isinsecure); +ATF_TC_HEAD(dns_acl_isinsecure, tc) { + atf_tc_set_md_var(tc, "descr", "test that dns_acl_isinsecure works"); +} +ATF_TC_BODY(dns_acl_isinsecure, tc) { + isc_result_t result; + unsigned int pass; + struct { + bool first; + bool second; + } ecs[] = { + { false, false }, + { true, true }, + { true, false }, + { false, true } + }; + + dns_acl_t *any = NULL; + dns_acl_t *none = NULL; + dns_acl_t *notnone = NULL; + dns_acl_t *notany = NULL; +#ifdef HAVE_GEOIP + dns_acl_t *geoip = NULL; + dns_acl_t *notgeoip = NULL; + dns_aclelement_t *de; +#endif + + dns_acl_t *pos4pos6 = NULL; + dns_acl_t *notpos4pos6 = NULL; + dns_acl_t *neg4pos6 = NULL; + dns_acl_t *notneg4pos6 = NULL; + dns_acl_t *pos4neg6 = NULL; + dns_acl_t *notpos4neg6 = NULL; + dns_acl_t *neg4neg6 = NULL; + dns_acl_t *notneg4neg6 = NULL; + + dns_acl_t *loop4 = NULL; + dns_acl_t *notloop4 = NULL; + + dns_acl_t *loop6 = NULL; + dns_acl_t *notloop6 = NULL; + + dns_acl_t *loop4pos6 = NULL; + dns_acl_t *notloop4pos6 = NULL; + dns_acl_t *loop4neg6 = NULL; + dns_acl_t *notloop4neg6 = NULL; + + struct in_addr inaddr; + isc_netaddr_t addr; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_any(mctx, &any); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_none(mctx, &none); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬none); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬any); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notnone, none, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notany, any, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + +#ifdef HAVE_GEOIP + result = dns_acl_create(mctx, 1, &geoip); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + de = geoip->elements; + ATF_REQUIRE(de != NULL); + strlcpy(de->geoip_elem.as_string, "AU", + sizeof(de->geoip_elem.as_string)); + de->geoip_elem.subtype = dns_geoip_country_code; + de->type = dns_aclelementtype_geoip; + de->negative = false; + ATF_REQUIRE(geoip->length < geoip->alloc); + geoip->node_count++; + de->node_num = geoip->node_count; + geoip->length++; + + result = dns_acl_create(mctx, 1, ¬geoip); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notgeoip, geoip, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); +#endif + + ATF_CHECK(dns_acl_isinsecure(any)); /* any; */ + ATF_CHECK(!dns_acl_isinsecure(none)); /* none; */ + ATF_CHECK(!dns_acl_isinsecure(notany)); /* !any; */ + ATF_CHECK(!dns_acl_isinsecure(notnone)); /* !none; */ + +#ifdef HAVE_GEOIP + ATF_CHECK(dns_acl_isinsecure(geoip)); /* geoip; */ + ATF_CHECK(!dns_acl_isinsecure(notgeoip)); /* !geoip; */ +#endif + + dns_acl_detach(&any); + dns_acl_detach(&none); + dns_acl_detach(¬any); + dns_acl_detach(¬none); +#ifdef HAVE_GEOIP + dns_acl_detach(&geoip); + dns_acl_detach(¬geoip); +#endif + + for (pass = 0; pass < sizeof(ecs)/sizeof(ecs[0]); pass++) { + result = dns_acl_create(mctx, 1, &pos4pos6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬pos4pos6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, &neg4pos6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬neg4pos6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, &pos4neg6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬pos4neg6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, &neg4neg6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬neg4neg6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + inaddr.s_addr = htonl(0x0a000000); /* 10.0.0.0 */ + isc_netaddr_fromin(&addr, &inaddr); + result = dns_iptable_addprefix2(pos4pos6->iptable, &addr, 8, + true, ecs[pass].first); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + addr.family = AF_INET6; /* 0a00:: */ + result = dns_iptable_addprefix2(pos4pos6->iptable, &addr, 8, + true, ecs[pass].second); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notpos4pos6, pos4pos6, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + inaddr.s_addr = htonl(0x0a000000); /* !10.0.0.0/8 */ + isc_netaddr_fromin(&addr, &inaddr); + result = dns_iptable_addprefix2(neg4pos6->iptable, &addr, 8, + false, ecs[pass].first); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + addr.family = AF_INET6; /* 0a00::/8 */ + result = dns_iptable_addprefix2(neg4pos6->iptable, &addr, 8, + true, ecs[pass].second); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notneg4pos6, neg4pos6, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + inaddr.s_addr = htonl(0x0a000000); /* 10.0.0.0/8 */ + isc_netaddr_fromin(&addr, &inaddr); + result = dns_iptable_addprefix2(pos4neg6->iptable, &addr, 8, + true, ecs[pass].first); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + addr.family = AF_INET6; /* !0a00::/8 */ + result = dns_iptable_addprefix2(pos4neg6->iptable, &addr, 8, + false, ecs[pass].second); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notpos4neg6, pos4neg6, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + inaddr.s_addr = htonl(0x0a000000); /* !10.0.0.0/8 */ + isc_netaddr_fromin(&addr, &inaddr); + result = dns_iptable_addprefix2(neg4neg6->iptable, &addr, 8, + false, ecs[pass].first); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + addr.family = AF_INET6; /* !0a00::/8 */ + result = dns_iptable_addprefix2(neg4neg6->iptable, &addr, 8, + false, ecs[pass].second); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notneg4neg6, neg4neg6, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_CHECK(dns_acl_isinsecure(pos4pos6)); + ATF_CHECK(!dns_acl_isinsecure(notpos4pos6)); + ATF_CHECK(dns_acl_isinsecure(neg4pos6)); + ATF_CHECK(!dns_acl_isinsecure(notneg4pos6)); + ATF_CHECK(dns_acl_isinsecure(pos4neg6)); + ATF_CHECK(!dns_acl_isinsecure(notpos4neg6)); + ATF_CHECK(!dns_acl_isinsecure(neg4neg6)); + ATF_CHECK(!dns_acl_isinsecure(notneg4neg6)); + + dns_acl_detach(&pos4pos6); + dns_acl_detach(¬pos4pos6); + dns_acl_detach(&neg4pos6); + dns_acl_detach(¬neg4pos6); + dns_acl_detach(&pos4neg6); + dns_acl_detach(¬pos4neg6); + dns_acl_detach(&neg4neg6); + dns_acl_detach(¬neg4neg6); + + result = dns_acl_create(mctx, 1, &loop4); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬loop4); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, &loop6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬loop6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + inaddr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ + isc_netaddr_fromin(&addr, &inaddr); + result = dns_iptable_addprefix2(loop4->iptable, &addr, 32, + true, ecs[pass].first); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notloop4, loop4, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_netaddr_fromin6(&addr, &in6addr_loopback); /* ::1 */ + result = dns_iptable_addprefix2(loop6->iptable, &addr, 128, + true, ecs[pass].first); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notloop6, loop6, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + if (!ecs[pass].first) { + ATF_CHECK(!dns_acl_isinsecure(loop4)); + ATF_CHECK(!dns_acl_isinsecure(notloop4)); + ATF_CHECK(!dns_acl_isinsecure(loop6)); + ATF_CHECK(!dns_acl_isinsecure(notloop6)); + } else if (ecs[pass].first) { + ATF_CHECK(dns_acl_isinsecure(loop4)); + ATF_CHECK(!dns_acl_isinsecure(notloop4)); + ATF_CHECK(dns_acl_isinsecure(loop6)); + ATF_CHECK(!dns_acl_isinsecure(notloop6)); + } + + dns_acl_detach(&loop4); + dns_acl_detach(¬loop4); + dns_acl_detach(&loop6); + dns_acl_detach(¬loop6); + + result = dns_acl_create(mctx, 1, &loop4pos6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬loop4pos6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, &loop4neg6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬loop4neg6); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + inaddr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ + isc_netaddr_fromin(&addr, &inaddr); + result = dns_iptable_addprefix2(loop4pos6->iptable, &addr, 32, + true, ecs[pass].first); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + addr.family = AF_INET6; /* f700:0001::/32 */ + result = dns_iptable_addprefix2(loop4pos6->iptable, &addr, 32, + true, ecs[pass].second); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notloop4pos6, loop4pos6, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + inaddr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ + isc_netaddr_fromin(&addr, &inaddr); + result = dns_iptable_addprefix2(loop4neg6->iptable, &addr, 32, + true, ecs[pass].first); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + addr.family = AF_INET6; /* !f700:0001::/32 */ + result = dns_iptable_addprefix2(loop4neg6->iptable, &addr, 32, + false, ecs[pass].second); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notloop4neg6, loop4neg6, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + if (!ecs[pass].first && !ecs[pass].second) { + ATF_CHECK(dns_acl_isinsecure(loop4pos6)); + ATF_CHECK(!dns_acl_isinsecure(notloop4pos6)); + ATF_CHECK(!dns_acl_isinsecure(loop4neg6)); + ATF_CHECK(!dns_acl_isinsecure(notloop4neg6)); + } else if (ecs[pass].first && !ecs[pass].second) { + ATF_CHECK(dns_acl_isinsecure(loop4pos6)); + ATF_CHECK(!dns_acl_isinsecure(notloop4pos6)); + ATF_CHECK(dns_acl_isinsecure(loop4neg6)); + ATF_CHECK(!dns_acl_isinsecure(notloop4neg6)); + } else if (!ecs[pass].first && ecs[pass].second) { + ATF_CHECK(dns_acl_isinsecure(loop4pos6)); + ATF_CHECK(!dns_acl_isinsecure(notloop4pos6)); + ATF_CHECK(!dns_acl_isinsecure(loop4neg6)); + ATF_CHECK(!dns_acl_isinsecure(notloop4neg6)); + } else { + ATF_CHECK(dns_acl_isinsecure(loop4pos6)); + ATF_CHECK(!dns_acl_isinsecure(notloop4pos6)); + ATF_CHECK(dns_acl_isinsecure(loop4neg6)); + ATF_CHECK(!dns_acl_isinsecure(notloop4neg6)); + } + + dns_acl_detach(&loop4pos6); + dns_acl_detach(¬loop4pos6); + dns_acl_detach(&loop4neg6); + dns_acl_detach(¬loop4neg6); + } + + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, dns_acl_isinsecure); + return (atf_no_error()); +} diff --git a/lib/dns/tests/db_test.c b/lib/dns/tests/db_test.c new file mode 100644 index 0000000..d12a497 --- /dev/null +++ b/lib/dns/tests/db_test.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> +#include <stdlib.h> + +#include <dns/db.h> +#include <dns/dbiterator.h> +#include <dns/name.h> +#include <dns/journal.h> + +#include "dnstest.h" + +/* + * Helper functions + */ + +#define BUFLEN 255 +#define BIGBUFLEN (64 * 1024) +#define TEST_ORIGIN "test" + +/* + * Individual unit tests + */ + +ATF_TC(getoriginnode); +ATF_TC_HEAD(getoriginnode, tc) { + atf_tc_set_md_var(tc, "descr", + "test multiple calls to dns_db_getoriginnode"); +} +ATF_TC_BODY(getoriginnode, tc) { + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + isc_mem_t *mymctx = NULL; + isc_result_t result; + + result = isc_mem_create(0, 0, &mymctx); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_hash_create(mymctx, NULL, 256); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_create(mymctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_getoriginnode(db, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + + result = dns_db_getoriginnode(db, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + + dns_db_detach(&db); + isc_mem_detach(&mymctx); +} + +ATF_TC(class); +ATF_TC_HEAD(class, tc) { + atf_tc_set_md_var(tc, "descr", "database class"); +} +ATF_TC_BODY(class, tc) { + isc_result_t result; + dns_db_t *db = NULL; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_load(db, "testdata/db/data.db"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_CHECK_EQ(dns_db_class(db), dns_rdataclass_in); + + dns_db_detach(&db); +} + +ATF_TC(dbtype); +ATF_TC_HEAD(dbtype, tc) { + atf_tc_set_md_var(tc, "descr", "database type"); +} +ATF_TC_BODY(dbtype, tc) { + isc_result_t result; + dns_db_t *db = NULL; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* DB has zone semantics */ + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_db_load(db, "testdata/db/data.db"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(dns_db_iszone(db)); + ATF_CHECK(!dns_db_iscache(db)); + dns_db_detach(&db); + + /* DB has cache semantics */ + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache, + dns_rdataclass_in, 0, NULL, &db); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_db_load(db, "testdata/db/data.db"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(dns_db_iscache(db)); + ATF_CHECK(!dns_db_iszone(db)); + dns_db_detach(&db); + + dns_test_end(); +} + +ATF_TC(version); +ATF_TC_HEAD(version, tc) { + atf_tc_set_md_var(tc, "descr", "database versions"); +} +ATF_TC_BODY(version, tc) { + isc_result_t result; + dns_fixedname_t fname, ffound; + dns_name_t *name, *foundname; + dns_db_t *db = NULL; + dns_dbversion_t *ver = NULL, *new = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_zone, "test.test", + "testdata/db/data.db"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Open current version for reading */ + dns_db_currentversion(db, &ver); + dns_test_namefromstring("b.test.test", &fname); + name = dns_fixedname_name(&fname); + foundname = dns_fixedname_initname(&ffound); + dns_rdataset_init(&rdataset); + result = dns_db_find(db, name , ver, dns_rdatatype_a, 0, 0, &node, + foundname, &rdataset, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + dns_db_closeversion(db, &ver, false); + + /* Open new version for writing */ + dns_db_currentversion(db, &ver); + dns_test_namefromstring("b.test.test", &fname); + name = dns_fixedname_name(&fname); + foundname = dns_fixedname_initname(&ffound); + dns_rdataset_init(&rdataset); + result = dns_db_find(db, name , ver, dns_rdatatype_a, 0, 0, &node, + foundname, &rdataset, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_newversion(db, &new); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Delete the rdataset from the new verison */ + result = dns_db_deleterdataset(db, node, new, dns_rdatatype_a, 0); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + + /* This should fail now */ + result = dns_db_find(db, name, new, dns_rdatatype_a, 0, 0, &node, + foundname, &rdataset, NULL); + ATF_REQUIRE_EQ(result, DNS_R_NXDOMAIN); + + dns_db_closeversion(db, &new, true); + + /* But this should still succeed */ + result = dns_db_find(db, name, ver, dns_rdatatype_a, 0, 0, &node, + foundname, &rdataset, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + dns_db_closeversion(db, &ver, false); + + dns_db_detach(&db); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, getoriginnode); + ATF_TP_ADD_TC(tp, class); + ATF_TP_ADD_TC(tp, dbtype); + ATF_TP_ADD_TC(tp, version); + + return (atf_no_error()); +} diff --git a/lib/dns/tests/dbdiff_test.c b/lib/dns/tests/dbdiff_test.c new file mode 100644 index 0000000..2ddd243 --- /dev/null +++ b/lib/dns/tests/dbdiff_test.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> +#include <stdlib.h> + +#include <dns/db.h> +#include <dns/dbiterator.h> +#include <dns/name.h> +#include <dns/journal.h> + +#include "dnstest.h" + +/* + * Helper functions + */ + +#define BUFLEN 255 +#define BIGBUFLEN (64 * 1024) +#define TEST_ORIGIN "test" + +static void +test_create(const atf_tc_t *tc, dns_db_t **old, dns_db_t **newdb) { + isc_result_t result; + + result = dns_test_loaddb(old, dns_dbtype_zone, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-old")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(newdb, dns_dbtype_zone, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-new")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); +} + +/* + * Individual unit tests + */ + +ATF_TC(diffx_same); +ATF_TC_HEAD(diffx_same, tc) { + atf_tc_set_md_var(tc, "descr", "dns_db_diffx of identical content"); + atf_tc_set_md_var(tc, "X-old", "testdata/diff/zone1.data"); + atf_tc_set_md_var(tc, "X-new", "testdata/diff/zone1.data"); } +ATF_TC_BODY(diffx_same, tc) { + dns_db_t *newdb = NULL, *olddb = NULL; + isc_result_t result; + dns_diff_t diff; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + test_create(tc, &olddb, &newdb); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, newdb, NULL, olddb, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(ISC_LIST_EMPTY(diff.tuples), true); + + dns_diff_clear(&diff); + dns_db_detach(&newdb); + dns_db_detach(&olddb); + dns_test_end(); +} + +ATF_TC(diffx_add); +ATF_TC_HEAD(diffx_add, tc) { + atf_tc_set_md_var(tc, "descr", + "dns_db_diffx of zone with record added"); + atf_tc_set_md_var(tc, "X-old", "testdata/diff/zone1.data"); + atf_tc_set_md_var(tc, "X-new", "testdata/diff/zone2.data"); +} +ATF_TC_BODY(diffx_add, tc) { + dns_db_t *newdb = NULL, *olddb = NULL; + dns_difftuple_t *tuple; + isc_result_t result; + dns_diff_t diff; + int count = 0; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + test_create(tc, &olddb, &newdb); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, newdb, NULL, olddb, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(ISC_LIST_EMPTY(diff.tuples), false); + for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + ATF_REQUIRE_EQ(tuple->op, DNS_DIFFOP_ADD); + count++; + } + ATF_REQUIRE_EQ(count, 1); + + dns_diff_clear(&diff); + dns_db_detach(&newdb); + dns_db_detach(&olddb); + dns_test_end(); +} + +ATF_TC(diffx_remove); +ATF_TC_HEAD(diffx_remove, tc) { + atf_tc_set_md_var(tc, "descr", + "dns_db_diffx of zone with record removed"); + atf_tc_set_md_var(tc, "X-old", "testdata/diff/zone1.data"); + atf_tc_set_md_var(tc, "X-new", "testdata/diff/zone3.data"); +} +ATF_TC_BODY(diffx_remove, tc) { + dns_db_t *newdb = NULL, *olddb = NULL; + dns_difftuple_t *tuple; + isc_result_t result; + dns_diff_t diff; + int count = 0; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + test_create(tc, &olddb, &newdb); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, newdb, NULL, olddb, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(ISC_LIST_EMPTY(diff.tuples), false); + for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + ATF_REQUIRE_EQ(tuple->op, DNS_DIFFOP_DEL); + count++; + } + ATF_REQUIRE_EQ(count, 1); + + dns_diff_clear(&diff); + dns_db_detach(&newdb); + dns_db_detach(&olddb); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, diffx_same); + ATF_TP_ADD_TC(tp, diffx_add); + ATF_TP_ADD_TC(tp, diffx_remove); + return (atf_no_error()); +} diff --git a/lib/dns/tests/dbiterator_test.c b/lib/dns/tests/dbiterator_test.c new file mode 100644 index 0000000..643627b --- /dev/null +++ b/lib/dns/tests/dbiterator_test.c @@ -0,0 +1,425 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> +#include <stdlib.h> + +#include <dns/db.h> +#include <dns/dbiterator.h> +#include <dns/name.h> + +#include "dnstest.h" + +/* + * Helper functions + */ + +#define BUFLEN 255 +#define BIGBUFLEN (64 * 1024) +#define TEST_ORIGIN "test" + +static isc_result_t +make_name(const char *src, dns_name_t *name) { + isc_buffer_t b; + isc_buffer_constinit(&b, src, strlen(src)); + isc_buffer_add(&b, strlen(src)); + return (dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); +} + +/* + * Individual unit tests + */ + +/* create: make sure we can create a dbiterator */ +static void +test_create(const atf_tc_t *tc) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); + dns_test_end(); +} + +ATF_TC(create); +ATF_TC_HEAD(create, tc) { + atf_tc_set_md_var(tc, "descr", "create a database iterator"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); +} +ATF_TC_BODY(create, tc) { + test_create(tc); +} + +ATF_TC(create_nsec3); +ATF_TC_HEAD(create_nsec3, tc) { + atf_tc_set_md_var(tc, "descr", "create a database iterator (NSEC3)"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); +} +ATF_TC_BODY(create_nsec3, tc) { + test_create(tc); +} + +/* walk: walk a database */ +static void +test_walk(const atf_tc_t *tc) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_dbnode_t *node = NULL; + dns_name_t *name; + dns_fixedname_t f; + int i = 0; + + UNUSED(tc); + + name = dns_fixedname_initname(&f); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (result = dns_dbiterator_first(iter); + result == ISC_R_SUCCESS; + result = dns_dbiterator_next(iter)) { + result = dns_dbiterator_current(iter, &node, name); + if (result == DNS_R_NEWORIGIN) + result = ISC_R_SUCCESS; + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + i++; + } + + ATF_CHECK_EQ(i, atoi(atf_tc_get_md_var(tc, "X-nodes"))); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); + dns_test_end(); +} + +ATF_TC(walk); +ATF_TC_HEAD(walk, tc) { + atf_tc_set_md_var(tc, "descr", "walk database"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); + atf_tc_set_md_var(tc, "X-nodes", "12"); +} +ATF_TC_BODY(walk, tc) { + test_walk(tc); +} + +ATF_TC(walk_nsec3); +ATF_TC_HEAD(walk_nsec3, tc) { + atf_tc_set_md_var(tc, "descr", "walk database"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); + atf_tc_set_md_var(tc, "X-nodes", "33"); +} +ATF_TC_BODY(walk_nsec3, tc) { + test_walk(tc); +} + +/* reverse: walk database backwards */ +static void test_reverse(const atf_tc_t *tc) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_dbnode_t *node = NULL; + dns_name_t *name; + dns_fixedname_t f; + int i = 0; + + UNUSED(tc); + + name = dns_fixedname_initname(&f); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (result = dns_dbiterator_last(iter); + result == ISC_R_SUCCESS; + result = dns_dbiterator_prev(iter)) { + result = dns_dbiterator_current(iter, &node, name); + if (result == DNS_R_NEWORIGIN) + result = ISC_R_SUCCESS; + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + i++; + } + + ATF_CHECK_EQ(i, 12); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); + dns_test_end(); +} + +ATF_TC(reverse); +ATF_TC_HEAD(reverse, tc) { + atf_tc_set_md_var(tc, "descr", "walk database backwards"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); +} +ATF_TC_BODY(reverse, tc) { + test_reverse(tc); +} + +ATF_TC(reverse_nsec3); +ATF_TC_HEAD(reverse_nsec3, tc) { + atf_tc_set_md_var(tc, "descr", "walk database backwards"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); +} +ATF_TC_BODY(reverse_nsec3, tc) { + test_reverse(tc); +} + +/* seek: walk database starting at a particular node */ +static void test_seek(const atf_tc_t *tc) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_dbnode_t *node = NULL; + dns_name_t *name, *seekname; + dns_fixedname_t f1, f2; + int i = 0; + + UNUSED(tc); + + name = dns_fixedname_initname(&f1); + seekname = dns_fixedname_initname(&f2); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = make_name("c." TEST_ORIGIN, seekname); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_dbiterator_seek(iter, seekname); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + while (result == ISC_R_SUCCESS) { + result = dns_dbiterator_current(iter, &node, name); + if (result == DNS_R_NEWORIGIN) + result = ISC_R_SUCCESS; + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + result = dns_dbiterator_next(iter); + i++; + } + + ATF_CHECK_EQ(i, atoi(atf_tc_get_md_var(tc, "X-nodes"))); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); + dns_test_end(); +} + +ATF_TC(seek); +ATF_TC_HEAD(seek, tc) { + atf_tc_set_md_var(tc, "descr", "walk database starting at " + "a particular node"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); + atf_tc_set_md_var(tc, "X-nodes", "9"); +} +ATF_TC_BODY(seek, tc) { + test_seek(tc); +} + +ATF_TC(seek_nsec3); +ATF_TC_HEAD(seek_nsec3, tc) { + atf_tc_set_md_var(tc, "descr", "walk database starting at " + "a particular node"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); + atf_tc_set_md_var(tc, "X-nodes", "30"); +} +ATF_TC_BODY(seek_nsec3, tc) { + test_seek(tc); +} + +/* + * seek_emty: walk database starting at an empty nonterminal node + * (should fail) + */ +static void test_seek_empty(const atf_tc_t *tc) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_name_t *seekname; + dns_fixedname_t f1; + + UNUSED(tc); + + seekname = dns_fixedname_initname(&f1); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = make_name("d." TEST_ORIGIN, seekname); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_dbiterator_seek(iter, seekname); + ATF_CHECK_EQ(result, DNS_R_PARTIALMATCH); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); + dns_test_end(); +} + +ATF_TC(seek_empty); +ATF_TC_HEAD(seek_empty, tc) { + atf_tc_set_md_var(tc, "descr", "walk database starting at an " + "empty nonterminal node"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); +} +ATF_TC_BODY(seek_empty, tc) { + test_seek_empty(tc); +} + +ATF_TC(seek_empty_nsec3); +ATF_TC_HEAD(seek_empty_nsec3, tc) { + atf_tc_set_md_var(tc, "descr", "walk database starting at an " + "empty nonterminal node"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); +} +ATF_TC_BODY(seek_empty_nsec3, tc) { + test_seek_empty(tc); +} + +/* + * seek_emty: walk database starting at an empty nonterminal node + * (should fail) + */ +static void test_seek_nx(const atf_tc_t *tc) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_name_t *seekname; + dns_fixedname_t f1; + + UNUSED(tc); + + seekname = dns_fixedname_initname(&f1); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = make_name("nonexistent." TEST_ORIGIN, seekname); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_dbiterator_seek(iter, seekname); + ATF_CHECK_EQ(result, DNS_R_PARTIALMATCH); + + result = make_name("nonexistent.", seekname); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_dbiterator_seek(iter, seekname); + ATF_CHECK_EQ(result, ISC_R_NOTFOUND); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); + dns_test_end(); +} + +ATF_TC(seek_nx); +ATF_TC_HEAD(seek_nx, tc) { + atf_tc_set_md_var(tc, "descr", "attempt to walk database starting " + "at a nonexistent node"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data"); +} +ATF_TC_BODY(seek_nx, tc) { + test_seek_nx(tc); +} + +ATF_TC(seek_nx_nsec3); +ATF_TC_HEAD(seek_nx_nsec3, tc) { + atf_tc_set_md_var(tc, "descr", "attempt to walk database starting " + "at a nonexistent node"); + atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data"); +} +ATF_TC_BODY(seek_nx_nsec3, tc) { + test_seek_nx(tc); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, create); + ATF_TP_ADD_TC(tp, create_nsec3); + ATF_TP_ADD_TC(tp, walk); + ATF_TP_ADD_TC(tp, walk_nsec3); + ATF_TP_ADD_TC(tp, reverse); + ATF_TP_ADD_TC(tp, reverse_nsec3); + ATF_TP_ADD_TC(tp, seek); + ATF_TP_ADD_TC(tp, seek_nsec3); + ATF_TP_ADD_TC(tp, seek_empty); + ATF_TP_ADD_TC(tp, seek_empty_nsec3); + ATF_TP_ADD_TC(tp, seek_nx); + ATF_TP_ADD_TC(tp, seek_nx_nsec3); + return (atf_no_error()); +} + +/* + * XXX: + * dns_dbiterator API calls that are not yet part of this unit test: + * + * dns_dbiterator_pause + * dns_dbiterator_origin + * dns_dbiterator_setcleanmode + */ diff --git a/lib/dns/tests/dbversion_test.c b/lib/dns/tests/dbversion_test.c new file mode 100644 index 0000000..275fc9b --- /dev/null +++ b/lib/dns/tests/dbversion_test.c @@ -0,0 +1,735 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <inttypes.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#include <atf-c.h> + +#include <isc/file.h> +#include <isc/result.h> +#include <isc/serial.h> +#include <isc/stdtime.h> +#include <isc/msgcat.h> + +#include <dns/db.h> +#include <dns/rdatalist.h> +#include <dns/rdataset.h> +#include <dns/rdatasetiter.h> +#include <dns/nsec3.h> + +#include "dnstest.h" + +static char tempname[11] = "dtXXXXXXXX"; + +static void +local_callback(const char *file, int line, isc_assertiontype_t type, + const char *cond) +{ + UNUSED(file); UNUSED(line); UNUSED(type); UNUSED(cond); + if (strcmp(tempname, "dtXXXXXXXX")) + unlink(tempname); + atf_tc_pass(); + exit(0); +} + +static dns_db_t *db1 = NULL, *db2 = NULL; +static dns_dbversion_t *v1 = NULL, *v2 = NULL; + +static void +setup_db(void) { + isc_result_t result; + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_db_newversion(db1, &v1); + + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db2); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_db_newversion(db2, &v2); +} + +static void +close_db(void) { + if (v1 != NULL) { + dns_db_closeversion(db1, &v1, false); + ATF_REQUIRE_EQ(v1, NULL); + } + if (db1 != NULL) { + dns_db_detach(&db1); + ATF_REQUIRE_EQ(db1, NULL); + } + + if (v2 != NULL) { + dns_db_closeversion(db2, &v2, false); + ATF_REQUIRE_EQ(v2, NULL); + } + if (db2 != NULL) { + dns_db_detach(&db2); + ATF_REQUIRE_EQ(db2, NULL); + } +} + +#define VERSION(callback) ((callback == NULL) ? v1 : v2) +#define VERSIONP(callback) ((callback == NULL) ? &v1 : &v2) +/* + * Individual unit tests + */ +static void +attachversion(isc_assertioncallback_t callback) { + isc_result_t result; + dns_dbversion_t *v = NULL; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + isc_assertion_setcallback(callback); + dns_db_attachversion(db1, VERSION(callback), &v); + if (callback != NULL) + atf_tc_fail("dns_db_attachversion did not assert"); + + ATF_REQUIRE_EQ(v, v1); + dns_db_closeversion(db1, &v, false); + ATF_REQUIRE_EQ(v, NULL); + + close_db(); + dns_test_end(); +} + +ATF_TC(attachversion); +ATF_TC_HEAD(attachversion, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_attachversion passes with matching db/verison"); +} +ATF_TC_BODY(attachversion, tc) { + + UNUSED(tc); + + attachversion(NULL); +} + +ATF_TC(attachversion_bad); +ATF_TC_HEAD(attachversion_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_attachversion aborts with mis-matching db/verison"); +} +ATF_TC_BODY(attachversion_bad, tc) { + + UNUSED(tc); + + attachversion(local_callback); +} + +static void +closeversion(isc_assertioncallback_t callback) { + isc_result_t result; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + isc_assertion_setcallback(callback); + dns_db_closeversion(db1, VERSIONP(callback), false); + if (callback != NULL) + atf_tc_fail("dns_db_closeversion did not assert"); + ATF_REQUIRE_EQ(v1, NULL); + + close_db(); + dns_test_end(); +} + +ATF_TC(closeversion); +ATF_TC_HEAD(closeversion, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_closeversion passes with matching db/verison"); +} +ATF_TC_BODY(closeversion, tc) { + + UNUSED(tc); + + closeversion(NULL); +} + +ATF_TC(closeversion_bad); +ATF_TC_HEAD(closeversion_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_closeversion asserts with mis-matching db/verison"); +} +ATF_TC_BODY(closeversion_bad, tc) { + + UNUSED(tc); + + closeversion(local_callback); +} + +static void +find(isc_assertioncallback_t callback) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_fixedname_t fixed; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + dns_rdataset_init(&rdataset); + dns_fixedname_init(&fixed); + + isc_assertion_setcallback(callback); + result = dns_db_find(db1, dns_rootname, VERSION(callback), + dns_rdatatype_soa, 0, 0, NULL, + dns_fixedname_name(&fixed), &rdataset, NULL); + if (callback != NULL) + atf_tc_fail("dns_db_find did not assert"); + ATF_REQUIRE_EQ(result, DNS_R_NXDOMAIN); + + close_db(); + + dns_test_end(); +} +ATF_TC(find); +ATF_TC_HEAD(find, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_find passes with matching db/version"); +} +ATF_TC_BODY(find, tc) { + + UNUSED(tc); + + find(NULL); +} + +ATF_TC(find_bad); +ATF_TC_HEAD(find_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_find asserts with mis-matching db/version"); +} +ATF_TC_BODY(find_bad, tc) { + + UNUSED(tc); + + find(local_callback); +} + +static void +allrdatasets(isc_assertioncallback_t callback) { + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_rdatasetiter_t *iterator = NULL; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + result = dns_db_findnode(db1, dns_rootname, false, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_assertion_setcallback(callback); + result = dns_db_allrdatasets(db1, node, VERSION(callback), 0, + &iterator); + if (callback != NULL) + atf_tc_fail("dns_db_allrdatasets did not assert"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_rdatasetiter_destroy(&iterator); + ATF_REQUIRE_EQ(iterator, NULL); + + dns_db_detachnode(db1, &node); + ATF_REQUIRE_EQ(node, NULL); + + close_db(); + + dns_test_end(); +} + +ATF_TC(allrdatasets); +ATF_TC_HEAD(allrdatasets, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_allrdatasets passes with matching db/version"); +} +ATF_TC_BODY(allrdatasets, tc) { + + UNUSED(tc); + + allrdatasets(NULL); +} + +ATF_TC(allrdatasets_bad); +ATF_TC_HEAD(allrdatasets_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_allrdatasets aborts with mis-matching db/version"); +} +ATF_TC_BODY(allrdatasets_bad, tc) { + + UNUSED(tc); + + allrdatasets(local_callback); +} + +static void +findrdataset(isc_assertioncallback_t callback) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_fixedname_t fixed; + dns_dbnode_t *node = NULL; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + dns_rdataset_init(&rdataset); + dns_fixedname_init(&fixed); + + result = dns_db_findnode(db1, dns_rootname, false, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_assertion_setcallback(callback); + result = dns_db_findrdataset(db1, node, VERSION(callback), + dns_rdatatype_soa, 0, 0, &rdataset, NULL); + if (callback != NULL) + atf_tc_fail("dns_db_findrdataset did not assert"); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + + dns_db_detachnode(db1, &node); + ATF_REQUIRE_EQ(node, NULL); + + close_db(); + + dns_test_end(); +} + +ATF_TC(findrdataset); +ATF_TC_HEAD(findrdataset, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_findrdataset passes with matching db/version"); +} +ATF_TC_BODY(findrdataset, tc) { + + UNUSED(tc); + + findrdataset(NULL); +} + +ATF_TC(findrdataset_bad); +ATF_TC_HEAD(findrdataset_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_findrdataset aborts with mis-matching db/version"); +} +ATF_TC_BODY(findrdataset_bad, tc) { + + UNUSED(tc); + + findrdataset(local_callback); +} + +static void +deleterdataset(isc_assertioncallback_t callback) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_fixedname_t fixed; + dns_dbnode_t *node = NULL; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + dns_rdataset_init(&rdataset); + dns_fixedname_init(&fixed); + + result = dns_db_findnode(db1, dns_rootname, false, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_assertion_setcallback(callback); + result = dns_db_deleterdataset(db1, node, VERSION(callback), + dns_rdatatype_soa, 0); + if (callback != NULL) + atf_tc_fail("dns_db_deleterdataset did not assert"); + ATF_REQUIRE_EQ(result, DNS_R_UNCHANGED); + + dns_db_detachnode(db1, &node); + ATF_REQUIRE_EQ(node, NULL); + + close_db(); + + dns_test_end(); +} + +ATF_TC(deleterdataset); +ATF_TC_HEAD(deleterdataset, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_deleterdataset passes with matching db/version"); +} +ATF_TC_BODY(deleterdataset, tc) { + + UNUSED(tc); + + deleterdataset(NULL); +} + +ATF_TC(deleterdataset_bad); +ATF_TC_HEAD(deleterdataset_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_deleterdataset aborts with mis-matching db/version"); +} +ATF_TC_BODY(deleterdataset_bad, tc) { + + UNUSED(tc); + + deleterdataset(local_callback); +} + +static void +subtract(isc_assertioncallback_t callback) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_fixedname_t fixed; + dns_dbnode_t *node = NULL; + dns_rdatalist_t rdatalist; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + dns_fixedname_init(&fixed); + + rdatalist.rdclass = dns_rdataclass_in; + + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_findnode(db1, dns_rootname, false, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_assertion_setcallback(callback); + result = dns_db_subtractrdataset(db1, node, VERSION(callback), + &rdataset, 0, NULL); + if (callback != NULL) + atf_tc_fail("dns_db_subtractrdataset did not assert"); + ATF_REQUIRE_EQ(result, DNS_R_UNCHANGED); + + dns_db_detachnode(db1, &node); + ATF_REQUIRE_EQ(node, NULL); + + close_db(); + + dns_test_end(); +} + +ATF_TC(subtractrdataset); +ATF_TC_HEAD(subtractrdataset, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_subtractrdataset passes with matching db/version"); +} +ATF_TC_BODY(subtractrdataset, tc) { + + UNUSED(tc); + + subtract(NULL); +} + +ATF_TC(subtractrdataset_bad); +ATF_TC_HEAD(subtractrdataset_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_subtractrdataset aborts with mis-matching db/version"); +} +ATF_TC_BODY(subtractrdataset_bad, tc) { + + UNUSED(tc); + + subtract(local_callback); +} + +static void +dump(isc_assertioncallback_t callback) { + isc_result_t result; + FILE *f = NULL; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + result = isc_file_openunique(tempname, &f); + fclose(f); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_assertion_setcallback(callback); + result = dns_db_dump(db1, VERSION(callback), tempname); + (void)unlink(tempname); + if (callback != NULL) + atf_tc_fail("dns_db_dump did not assert"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + close_db(); + + dns_test_end(); +} + +ATF_TC(dump); +ATF_TC_HEAD(dump, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_dump passes with matching db/version"); +} +ATF_TC_BODY(dump, tc) { + + UNUSED(tc); + + dump(NULL); +} + +ATF_TC(dump_bad); +ATF_TC_HEAD(dump_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_dump aborts with mis-matching db/version"); +} +ATF_TC_BODY(dump_bad, tc) { + + UNUSED(tc); + + dump(local_callback); +} + +static void +addrdataset(isc_assertioncallback_t callback) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_fixedname_t fixed; + dns_dbnode_t *node = NULL; + dns_rdatalist_t rdatalist; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + dns_fixedname_init(&fixed); + + rdatalist.rdclass = dns_rdataclass_in; + + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_findnode(db1, dns_rootname, false, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_assertion_setcallback(callback); + result = dns_db_addrdataset(db1, node, VERSION(callback), 0, &rdataset, + 0, NULL); + if (callback != NULL) + atf_tc_fail("dns_db_adddataset did not assert"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_db_detachnode(db1, &node); + ATF_REQUIRE_EQ(node, NULL); + + close_db(); + + dns_test_end(); +} + +ATF_TC(addrdataset); +ATF_TC_HEAD(addrdataset, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_addrdataset passes with matching db/version"); +} +ATF_TC_BODY(addrdataset, tc) { + + UNUSED(tc); + + addrdataset(NULL); +} + +ATF_TC(addrdataset_bad); +ATF_TC_HEAD(addrdataset_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_addrdataset aborts with mis-matching db/version"); +} +ATF_TC_BODY(addrdataset_bad, tc) { + + UNUSED(tc); + + addrdataset(local_callback); +} + +static void +getnsec3parameters(isc_assertioncallback_t callback) { + isc_result_t result; + dns_hash_t hash; + uint8_t flags; + uint16_t iterations; + unsigned char salt[DNS_NSEC3_SALTSIZE]; + size_t salt_length = sizeof(salt); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + isc_assertion_setcallback(callback); + result = dns_db_getnsec3parameters(db1, VERSION(callback), &hash, + &flags, &iterations, salt, + &salt_length); + if (callback != NULL) + atf_tc_fail("dns_db_dump did not assert"); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + + close_db(); + + dns_test_end(); +} + +ATF_TC(getnsec3parameters); +ATF_TC_HEAD(getnsec3parameters, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_getnsec3parameters passes with matching db/version"); +} +ATF_TC_BODY(getnsec3parameters, tc) { + + UNUSED(tc); + + getnsec3parameters(NULL); +} + +ATF_TC(getnsec3parameters_bad); +ATF_TC_HEAD(getnsec3parameters_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_db_getnsec3parameters aborts with mis-matching db/version"); +} +ATF_TC_BODY(getnsec3parameters_bad, tc) { + + UNUSED(tc); + + getnsec3parameters(local_callback); +} + +static void +resigned(isc_assertioncallback_t callback) { + isc_result_t result; + dns_rdataset_t rdataset, added; + dns_dbnode_t *node = NULL; + dns_rdatalist_t rdatalist; + dns_rdata_rrsig_t rrsig; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_buffer_t b; + unsigned char buf[1024]; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + setup_db(); + + /* + * Create a dummy RRSIG record and set a resigning time. + */ + dns_rdataset_init(&added); + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + isc_buffer_init(&b, buf, sizeof(buf)); + + DNS_RDATACOMMON_INIT(&rrsig, dns_rdatatype_rrsig, dns_rdataclass_in); + rrsig.covered = dns_rdatatype_a; + rrsig.algorithm = 100; + rrsig.labels = 0; + rrsig.originalttl = 0; + rrsig.timeexpire = 3600; + rrsig.timesigned = 0; + rrsig.keyid = 0; + dns_name_init(&rrsig.signer, NULL); + dns_name_clone(dns_rootname, &rrsig.signer); + rrsig.siglen = 0; + rrsig.signature = NULL; + + result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in, + dns_rdatatype_rrsig, &rrsig, &b); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + rdatalist.rdclass = dns_rdataclass_in; + rdatalist.type = dns_rdatatype_rrsig; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + rdataset.attributes |= DNS_RDATASETATTR_RESIGN; + rdataset.resign = 7200; + + result = dns_db_findnode(db1, dns_rootname, false, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_addrdataset(db1, node, v1, 0, &rdataset, 0, &added); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_db_detachnode(db1, &node); + ATF_REQUIRE_EQ(node, NULL); + + isc_assertion_setcallback(callback); + dns_db_resigned(db1, &added, VERSION(callback)); + if (callback != NULL) + atf_tc_fail("dns_db_resigned did not assert"); + + dns_rdataset_disassociate(&added); + + close_db(); + + dns_test_end(); +} + +ATF_TC(resigned); +ATF_TC_HEAD(resigned, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_rdataset_resigned passes with matching db/version"); +} +ATF_TC_BODY(resigned, tc) { + + UNUSED(tc); + + resigned(NULL); +} + +ATF_TC(resigned_bad); +ATF_TC_HEAD(resigned_bad, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_rdataset_resigned aborts with mis-matching db/version"); +} +ATF_TC_BODY(resigned_bad, tc) { + + UNUSED(tc); + + resigned(local_callback); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, dump); + ATF_TP_ADD_TC(tp, dump_bad); + ATF_TP_ADD_TC(tp, find); + ATF_TP_ADD_TC(tp, find_bad); + ATF_TP_ADD_TC(tp, allrdatasets); + ATF_TP_ADD_TC(tp, allrdatasets_bad); + ATF_TP_ADD_TC(tp, findrdataset); + ATF_TP_ADD_TC(tp, findrdataset_bad); + ATF_TP_ADD_TC(tp, addrdataset); + ATF_TP_ADD_TC(tp, addrdataset_bad); + ATF_TP_ADD_TC(tp, deleterdataset); + ATF_TP_ADD_TC(tp, deleterdataset_bad); + ATF_TP_ADD_TC(tp, subtractrdataset); + ATF_TP_ADD_TC(tp, subtractrdataset_bad); + ATF_TP_ADD_TC(tp, attachversion); + ATF_TP_ADD_TC(tp, attachversion_bad); + ATF_TP_ADD_TC(tp, closeversion); + ATF_TP_ADD_TC(tp, closeversion_bad); + ATF_TP_ADD_TC(tp, getnsec3parameters); + ATF_TP_ADD_TC(tp, getnsec3parameters_bad); + ATF_TP_ADD_TC(tp, resigned); + ATF_TP_ADD_TC(tp, resigned_bad); + + return (atf_no_error()); +} diff --git a/lib/dns/tests/dh_test.c b/lib/dns/tests/dh_test.c new file mode 100644 index 0000000..6216b4e --- /dev/null +++ b/lib/dns/tests/dh_test.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* ! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> + +#include <isc/util.h> +#include <isc/string.h> + +#include <pk11/site.h> + +#include <dns/name.h> +#include <dst/result.h> + +#include "../dst_internal.h" + +#include "dnstest.h" + +#if defined(OPENSSL) && !defined(PK11_DH_DISABLE) + +ATF_TC(isc_dh_computesecret); +ATF_TC_HEAD(isc_dh_computesecret, tc) { + atf_tc_set_md_var(tc, "descr", "OpenSSL DH_compute_key() failure"); +} +ATF_TC_BODY(isc_dh_computesecret, tc) { + dst_key_t *key = NULL; + isc_buffer_t buf; + unsigned char array[1024]; + isc_result_t ret; + dns_fixedname_t fname; + dns_name_t *name; + + UNUSED(tc); + + ret = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + name = dns_fixedname_initname(&fname); + isc_buffer_constinit(&buf, "dh.", 3); + isc_buffer_add(&buf, 3); + ret = dns_name_fromtext(name, &buf, NULL, 0, NULL); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + ret = dst_key_fromfile(name, 18602, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_KEY, + "./", mctx, &key); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + isc_buffer_init(&buf, array, sizeof(array)); + ret = dst_key_computesecret(key, key, &buf); + ATF_REQUIRE_EQ(ret, DST_R_NOTPRIVATEKEY); + ret = key->func->computesecret(key, key, &buf); + ATF_REQUIRE_EQ(ret, DST_R_COMPUTESECRETFAILURE); + + dst_key_free(&key); + dns_test_end(); +} +#else +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping OpenSSL DH test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("OpenSSL DH not compiled in"); +} +#endif +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { +#if defined(OPENSSL) && !defined(PK11_DH_DISABLE) + ATF_TP_ADD_TC(tp, isc_dh_computesecret); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + return (atf_no_error()); +} diff --git a/lib/dns/tests/dispatch_test.c b/lib/dns/tests/dispatch_test.c new file mode 100644 index 0000000..156fe9f --- /dev/null +++ b/lib/dns/tests/dispatch_test.c @@ -0,0 +1,341 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <inttypes.h> +#include <stdbool.h> +#include <unistd.h> + +#include <atf-c.h> + +#include <isc/app.h> +#include <isc/buffer.h> +#include <isc/socket.h> +#include <isc/task.h> +#include <isc/timer.h> + +#include <dns/dispatch.h> +#include <dns/name.h> +#include <dns/view.h> + +#include "dnstest.h" + +dns_dispatchmgr_t *dispatchmgr = NULL; +dns_dispatchset_t *dset = NULL; + +static isc_result_t +make_dispatchset(unsigned int ndisps) { + isc_result_t result; + isc_sockaddr_t any; + unsigned int attrs; + dns_dispatch_t *disp = NULL; + + result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr); + if (result != ISC_R_SUCCESS) + return (result); + + isc_sockaddr_any(&any); + attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; + result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, + &any, 512, 6, 1024, 17, 19, attrs, + attrs, &disp); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_dispatchset_create(mctx, socketmgr, taskmgr, disp, + &dset, ndisps); + dns_dispatch_detach(&disp); + + return (result); +} + +static void +teardown(void) { + if (dset != NULL) + dns_dispatchset_destroy(&dset); + if (dispatchmgr != NULL) + dns_dispatchmgr_destroy(&dispatchmgr); +} + +/* + * Individual unit tests + */ +ATF_TC(dispatchset_create); +ATF_TC_HEAD(dispatchset_create, tc) { + atf_tc_set_md_var(tc, "descr", "create dispatch set"); +} +ATF_TC_BODY(dispatchset_create, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = make_dispatchset(1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + teardown(); + + result = make_dispatchset(10); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + teardown(); + + dns_test_end(); +} + +ATF_TC(dispatchset_get); +ATF_TC_HEAD(dispatchset_get, tc) { + atf_tc_set_md_var(tc, "descr", "test dispatch set round-robin"); +} +ATF_TC_BODY(dispatchset_get, tc) { + isc_result_t result; + dns_dispatch_t *d1, *d2, *d3, *d4, *d5; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = make_dispatchset(1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + d1 = dns_dispatchset_get(dset); + d2 = dns_dispatchset_get(dset); + d3 = dns_dispatchset_get(dset); + d4 = dns_dispatchset_get(dset); + d5 = dns_dispatchset_get(dset); + + ATF_CHECK_EQ(d1, d2); + ATF_CHECK_EQ(d2, d3); + ATF_CHECK_EQ(d3, d4); + ATF_CHECK_EQ(d4, d5); + + teardown(); + + result = make_dispatchset(4); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + d1 = dns_dispatchset_get(dset); + d2 = dns_dispatchset_get(dset); + d3 = dns_dispatchset_get(dset); + d4 = dns_dispatchset_get(dset); + d5 = dns_dispatchset_get(dset); + + ATF_CHECK_EQ(d1, d5); + ATF_CHECK(d1 != d2); + ATF_CHECK(d2 != d3); + ATF_CHECK(d3 != d4); + ATF_CHECK(d4 != d5); + + teardown(); + dns_test_end(); +} + +static void +senddone(isc_task_t *task, isc_event_t *event) { + isc_socket_t *sock = event->ev_arg; + + UNUSED(task); + + isc_socket_detach(&sock); + isc_event_free(&event); +} + +static void +nameserver(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_region_t region; + isc_socket_t *dummy; + isc_socket_t *sock = event->ev_arg; + isc_socketevent_t *ev = (isc_socketevent_t *)event; + static unsigned char buf1[16]; + static unsigned char buf2[16]; + + memmove(buf1, ev->region.base, 12); + memset(buf1 + 12, 0, 4); + buf1[2] |= 0x80; /* qr=1 */ + + memmove(buf2, ev->region.base, 12); + memset(buf2 + 12, 1, 4); + buf2[2] |= 0x80; /* qr=1 */ + + /* + * send message to be discarded. + */ + region.base = buf1; + region.length = sizeof(buf1); + dummy = NULL; + isc_socket_attach(sock, &dummy); + result = isc_socket_sendto(sock, ®ion, task, senddone, sock, + &ev->address, NULL); + if (result != ISC_R_SUCCESS) + isc_socket_detach(&dummy); + + /* + * send nextitem message. + */ + region.base = buf2; + region.length = sizeof(buf2); + dummy = NULL; + isc_socket_attach(sock, &dummy); + result = isc_socket_sendto(sock, ®ion, task, senddone, sock, + &ev->address, NULL); + if (result != ISC_R_SUCCESS) + isc_socket_detach(&dummy); + isc_event_free(&event); +} + +static dns_dispatch_t *dispatch = NULL; +static dns_dispentry_t *dispentry = NULL; +static bool first = true; +static isc_mutex_t lock; +static isc_sockaddr_t local; +static unsigned int responses = 0; + +static void +response(isc_task_t *task, isc_event_t *event) { + dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event; + isc_result_t result; + bool wasfirst; + + UNUSED(task); + + LOCK(&lock); + wasfirst = first; + first = false; + responses++; + UNLOCK(&lock); + + if (wasfirst) { + result = dns_dispatch_getnext(dispentry, &devent); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + } else { + dns_dispatch_removeresponse(&dispentry, &devent); + isc_app_shutdown(); + } +} + +static void +startit(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_socket_t *sock = NULL; + + isc_socket_attach(dns_dispatch_getsocket(dispatch), &sock); + result = isc_socket_sendto(sock, event->ev_arg, task, senddone, sock, + &local, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_event_free(&event); +} + +ATF_TC(dispatch_getnext); +ATF_TC_HEAD(dispatch_getnext, tc) { + atf_tc_set_md_var(tc, "descr", "test dispatch getnext"); +} +ATF_TC_BODY(dispatch_getnext, tc) { + isc_region_t region; + isc_result_t result; + isc_socket_t *sock = NULL; + isc_task_t *task = NULL; + uint16_t id; + struct in_addr ina; + unsigned char message[12]; + unsigned int attrs; + unsigned char rbuf[12]; + + UNUSED(tc); + + result = isc_mutex_init(&lock); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_task_create(taskmgr, 0, &task); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ina.s_addr = htonl(INADDR_LOOPBACK); + isc_sockaddr_fromin(&local, &ina, 0); + attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; + result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, + &local, 512, 6, 1024, 17, 19, attrs, + attrs, &dispatch); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Create a local udp nameserver on the loopback. + */ + result = isc_socket_create(socketmgr, AF_INET, isc_sockettype_udp, + &sock); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ina.s_addr = htonl(INADDR_LOOPBACK); + isc_sockaddr_fromin(&local, &ina, 0); + result = isc_socket_bind(sock, &local, 0); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_socket_getsockname(sock, &local); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + first = true; + region.base = rbuf; + region.length = sizeof(rbuf); + result = isc_socket_recv(sock, ®ion, 1, task, nameserver, sock); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_dispatch_addresponse(dispatch, &local, task, response, + NULL, &id, &dispentry); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + memset(message, 0, sizeof(message)); + message[0] = (id >> 8) & 0xff; + message[1] = id & 0xff; + + region.base = message; + region.length = sizeof(message); + result = isc_app_onrun(mctx, task, startit, ®ion); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_app_run(); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_CHECK_EQ(responses, 2); + + /* + * Shutdown nameserver. + */ + isc_socket_cancel(sock, task, ISC_SOCKCANCEL_RECV); + isc_socket_detach(&sock); + isc_task_detach(&task); + + /* + * Shutdown the dispatch. + */ + dns_dispatch_detach(&dispatch); + dns_dispatchmgr_destroy(&dispatchmgr); + + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, dispatchset_create); + ATF_TP_ADD_TC(tp, dispatchset_get); + ATF_TP_ADD_TC(tp, dispatch_getnext); + return (atf_no_error()); +} diff --git a/lib/dns/tests/dnstap_test.c b/lib/dns/tests/dnstap_test.c new file mode 100644 index 0000000..56e3da4 --- /dev/null +++ b/lib/dns/tests/dnstap_test.c @@ -0,0 +1,383 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> +#include <inttypes.h> +#include <stdlib.h> + +#include <isc/buffer.h> +#include <isc/file.h> +#include <isc/stdio.h> +#include <isc/print.h> +#include <isc/types.h> + +#include <dns/dnstap.h> +#include <dns/view.h> + +#include "dnstest.h" + +#ifdef HAVE_DNSTAP +#include <dns/dnstap.pb-c.h> +#include <protobuf-c/protobuf-c.h> + +#define TAPFILE "testdata/dnstap/dnstap.file" +#define TAPSOCK "testdata/dnstap/dnstap.sock" + +#define TAPSAVED "testdata/dnstap/dnstap.saved" +#define TAPTEXT "testdata/dnstap/dnstap.text" + +/* + * Helper functions + */ +static void +cleanup() { + (void) isc_file_remove(TAPFILE); + (void) isc_file_remove(TAPSOCK); +} + +/* + * Individual unit tests + */ + +ATF_TC(create); +ATF_TC_HEAD(create, tc) { + atf_tc_set_md_var(tc, "descr", "set up dnstap environment"); +} +ATF_TC_BODY(create, tc) { + isc_result_t result; + dns_dtenv_t *dtenv = NULL; + struct fstrm_iothr_options *fopt; + + UNUSED(tc); + + cleanup(); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + fopt = fstrm_iothr_options_init(); + ATF_REQUIRE(fopt != NULL); + fstrm_iothr_options_set_num_input_queues(fopt, 1); + + result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, &fopt, &dtenv); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + if (dtenv != NULL) + dns_dt_detach(&dtenv); + if (fopt != NULL) + fstrm_iothr_options_destroy(&fopt); + + ATF_CHECK(isc_file_exists(TAPFILE)); + + fopt = fstrm_iothr_options_init(); + ATF_REQUIRE(fopt != NULL); + fstrm_iothr_options_set_num_input_queues(fopt, 1); + + result = dns_dt_create(mctx, dns_dtmode_unix, TAPSOCK, &fopt, &dtenv); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + if (dtenv != NULL) + dns_dt_detach(&dtenv); + if (fopt != NULL) + fstrm_iothr_options_destroy(&fopt); + + /* 'create' should succeed, but the file shouldn't exist yet */ + ATF_CHECK(!isc_file_exists(TAPSOCK)); + + fopt = fstrm_iothr_options_init(); + ATF_REQUIRE(fopt != NULL); + fstrm_iothr_options_set_num_input_queues(fopt, 1); + + result = dns_dt_create(mctx, 33, TAPSOCK, &fopt, &dtenv); + ATF_CHECK_EQ(result, ISC_R_FAILURE); + ATF_CHECK_EQ(dtenv, NULL); + if (dtenv != NULL) + dns_dt_detach(&dtenv); + if (fopt != NULL) + fstrm_iothr_options_destroy(&fopt); + + cleanup(); + + dns_dt_shutdown(); + dns_test_end(); +} + +ATF_TC(send); +ATF_TC_HEAD(send, tc) { + atf_tc_set_md_var(tc, "descr", "send dnstap messages"); +} +ATF_TC_BODY(send, tc) { + isc_result_t result; + dns_dtenv_t *dtenv = NULL; + dns_dthandle_t *handle = NULL; + uint8_t *data; + size_t dsize; + unsigned char zone[DNS_NAME_MAXWIRE]; + unsigned char qambuffer[4096], rambuffer[4096]; + unsigned char qrmbuffer[4096], rrmbuffer[4096]; + isc_buffer_t zb, qamsg, ramsg, qrmsg, rrmsg; + size_t qasize, qrsize, rasize, rrsize; + dns_fixedname_t zfname; + dns_name_t *zname; + dns_dtmsgtype_t dt; + dns_view_t *view = NULL; + dns_compress_t cctx; + isc_region_t zr; + isc_sockaddr_t qaddr; + isc_sockaddr_t raddr; + struct in_addr in; + isc_stdtime_t now; + isc_time_t p, f; + struct fstrm_iothr_options *fopt; + + UNUSED(tc); + + cleanup(); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + result = dns_test_makeview("test", &view); + + fopt = fstrm_iothr_options_init(); + ATF_REQUIRE(fopt != NULL); + fstrm_iothr_options_set_num_input_queues(fopt, 1); + + result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, &fopt, &dtenv); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + dns_dt_attach(dtenv, &view->dtenv); + view->dttypes = DNS_DTTYPE_ALL; + + /* + * Set up some test data + */ + zname = dns_fixedname_initname(&zfname); + isc_buffer_constinit(&zb, "example.com.", 12); + isc_buffer_add(&zb, 12); + result = dns_name_fromtext(zname, &zb, NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + memset(&zr, 0, sizeof(zr)); + isc_buffer_init(&zb, zone, sizeof(zone)); + result = dns_compress_init(&cctx, -1, mctx); + dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE); + result = dns_name_towire(zname, &cctx, &zb); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_compress_invalidate(&cctx); + isc_buffer_usedregion(&zb, &zr); + + in.s_addr = inet_addr("10.53.0.1"); + isc_sockaddr_fromin(&qaddr, &in, 2112); + in.s_addr = inet_addr("10.53.0.2"); + isc_sockaddr_fromin(&raddr, &in, 2112); + + isc_stdtime_get(&now); + isc_time_set(&p, now - 3600, 0); /* past */ + isc_time_set(&f, now + 3600, 0); /* future */ + + result = dns_test_getdata("testdata/dnstap/query.auth", + qambuffer, sizeof(qambuffer), &qasize); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_buffer_init(&qamsg, qambuffer, qasize); + isc_buffer_add(&qamsg, qasize); + + result = dns_test_getdata("testdata/dnstap/response.auth", + rambuffer, sizeof(rambuffer), &rasize); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_buffer_init(&ramsg, rambuffer, rasize); + isc_buffer_add(&ramsg, rasize); + + result = dns_test_getdata("testdata/dnstap/query.recursive", qrmbuffer, + sizeof(qrmbuffer), &qrsize); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_buffer_init(&qrmsg, qrmbuffer, qrsize); + isc_buffer_add(&qrmsg, qrsize); + + result = dns_test_getdata("testdata/dnstap/response.recursive", + rrmbuffer, sizeof(rrmbuffer), &rrsize); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_buffer_init(&rrmsg, rrmbuffer, rrsize); + isc_buffer_add(&rrmsg, rrsize); + + for (dt = DNS_DTTYPE_SQ; dt <= DNS_DTTYPE_TR; dt <<= 1) { + isc_buffer_t *m; + isc_sockaddr_t *q = &qaddr, *r = &raddr; + + switch (dt) { + case DNS_DTTYPE_AQ: + m = &qamsg; + break; + case DNS_DTTYPE_AR: + m = &ramsg; + break; + default: + m = &qrmsg; + if ((dt & DNS_DTTYPE_RESPONSE) != 0) + m = &ramsg; + break; + } + + dns_dt_send(view, dt, q, r, false, &zr, &p, &f, m); + dns_dt_send(view, dt, q, r, false, &zr, NULL, &f, m); + dns_dt_send(view, dt, q, r, false, &zr, &p, NULL, m); + dns_dt_send(view, dt, q, r, false, &zr, NULL, NULL, m); + dns_dt_send(view, dt, q, r, true, &zr, &p, &f, m); + dns_dt_send(view, dt, q, r, true, &zr, NULL, &f, m); + dns_dt_send(view, dt, q, r, true, &zr, &p, NULL, m); + dns_dt_send(view, dt, q, r, true, &zr, NULL, NULL, m); + } + + dns_dt_detach(&view->dtenv); + dns_dt_detach(&dtenv); + dns_dt_shutdown(); + dns_view_detach(&view); + + /* + * XXX now read back and check content. + */ + + result = dns_dt_open(TAPFILE, dns_dtmode_file, mctx, &handle); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + while (dns_dt_getframe(handle, &data, &dsize) == ISC_R_SUCCESS) { + dns_dtdata_t *dtdata = NULL; + isc_region_t r; + static dns_dtmsgtype_t expected = DNS_DTTYPE_SQ; + static int n = 0; + + r.base = data; + r.length = dsize; + + result = dns_dt_parse(mctx, &r, &dtdata); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) { + n++; + continue; + } + + ATF_CHECK_EQ(dtdata->type, expected); + if (++n % 8 == 0) + expected <<= 1; + + dns_dtdata_free(&dtdata); + } + + if (fopt != NULL) + fstrm_iothr_options_destroy(&fopt); + if (handle != NULL) + dns_dt_close(&handle); + cleanup(); + + dns_test_end(); +} + +ATF_TC(totext); +ATF_TC_HEAD(totext, tc) { + atf_tc_set_md_var(tc, "descr", "dnstap message to text"); +} +ATF_TC_BODY(totext, tc) { + isc_result_t result; + dns_dthandle_t *handle = NULL; + uint8_t *data; + size_t dsize; + FILE *fp = NULL; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + result = dns_dt_open(TAPSAVED, dns_dtmode_file, mctx, &handle); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_stdio_open(TAPTEXT, "r", &fp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* make sure text conversion gets the right local time */ + setenv("TZ", "PST8", 1); + + while (dns_dt_getframe(handle, &data, &dsize) == ISC_R_SUCCESS) { + dns_dtdata_t *dtdata = NULL; + isc_buffer_t *b = NULL; + isc_region_t r; + char s[BUFSIZ], *p; + + r.base = data; + r.length = dsize; + + /* read the corresponding line of text */ + p = fgets(s, sizeof(s), fp); + ATF_CHECK_EQ(p, s); + if (p == NULL) + break; + + p = strchr(p, '\n'); + if (p != NULL) + *p = '\0'; + + /* parse dnstap frame */ + result = dns_dt_parse(mctx, &r, &dtdata); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + continue; + + isc_buffer_allocate(mctx, &b, 2048); + ATF_CHECK(b != NULL); + if (b == NULL) + break; + + /* convert to text and compare */ + result = dns_dt_datatotext(dtdata, &b); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ATF_CHECK_STREQ((char *) isc_buffer_base(b), s); + + dns_dtdata_free(&dtdata); + isc_buffer_free(&b); + } + + if (handle != NULL) + dns_dt_close(&handle); + cleanup(); + + dns_test_end(); +} + +#else +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping dnstap test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("dnstap not available"); +} +#endif + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { +#ifdef HAVE_DNSTAP + ATF_TP_ADD_TC(tp, create); + ATF_TP_ADD_TC(tp, send); + ATF_TP_ADD_TC(tp, totext); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + + return (atf_no_error()); +} diff --git a/lib/dns/tests/dnstest.c b/lib/dns/tests/dnstest.c new file mode 100644 index 0000000..51bb90b --- /dev/null +++ b/lib/dns/tests/dnstest.c @@ -0,0 +1,596 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <inttypes.h> +#include <stdbool.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#include <isc/app.h> +#include <isc/buffer.h> +#include <isc/entropy.h> +#include <isc/file.h> +#include <isc/hash.h> +#include <isc/hex.h> +#include <isc/lex.h> +#include <isc/mem.h> +#include <isc/os.h> +#include <isc/print.h> +#include <isc/string.h> +#include <isc/socket.h> +#include <isc/stdio.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/fixedname.h> +#include <dns/log.h> +#include <dns/name.h> +#include <dns/result.h> +#include <dns/view.h> +#include <dns/zone.h> + +#include "dnstest.h" + +isc_mem_t *mctx = NULL; +isc_entropy_t *ectx = NULL; +isc_log_t *lctx = NULL; +isc_taskmgr_t *taskmgr = NULL; +isc_task_t *maintask = NULL; +isc_timermgr_t *timermgr = NULL; +isc_socketmgr_t *socketmgr = NULL; +dns_zonemgr_t *zonemgr = NULL; +bool app_running = false; +int ncpus; +bool debug_mem_record = true; + +static bool hash_active = false, dst_active = false; + +/* + * Logging categories: 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 }, + { "query-errors", 0 }, + { NULL, 0 } +}; + +static void +cleanup_managers(void) { + if (app_running) + isc_app_finish(); + if (socketmgr != NULL) + isc_socketmgr_destroy(&socketmgr); + if (maintask != NULL) + isc_task_destroy(&maintask); + if (taskmgr != NULL) + isc_taskmgr_destroy(&taskmgr); + if (timermgr != NULL) + isc_timermgr_destroy(&timermgr); +} + +static isc_result_t +create_managers(void) { + isc_result_t result; +#ifdef ISC_PLATFORM_USETHREADS + ncpus = isc_os_ncpus(); +#else + ncpus = 1; +#endif + + CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr)); + CHECK(isc_timermgr_create(mctx, &timermgr)); + CHECK(isc_socketmgr_create(mctx, &socketmgr)); + CHECK(isc_task_create(taskmgr, 0, &maintask)); + return (ISC_R_SUCCESS); + + cleanup: + cleanup_managers(); + return (result); +} + +isc_result_t +dns_test_begin(FILE *logfile, bool start_managers) { + isc_result_t result; + + if (start_managers) + CHECK(isc_app_start()); + if (debug_mem_record) + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + CHECK(isc_mem_create(0, 0, &mctx)); + CHECK(isc_entropy_create(mctx, &ectx)); + + CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)); + hash_active = true; + + CHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING)); + dst_active = true; + + if (logfile != NULL) { + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + + CHECK(isc_log_create(mctx, &lctx, &logconfig)); + isc_log_registercategories(lctx, categories); + isc_log_setcontext(lctx); + dns_log_init(lctx); + dns_log_setcontext(lctx); + + destination.file.stream = logfile; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + CHECK(isc_log_createchannel(logconfig, "stderr", + ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, + &destination, 0)); + CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL)); + } + + dns_result_register(); + + if (start_managers) + CHECK(create_managers()); + + /* + * atf-run changes us to a /tmp directory, so tests + * that access test data files must first chdir to the proper + * location. + */ + if (chdir(TESTS) == -1) + CHECK(ISC_R_FAILURE); + + return (ISC_R_SUCCESS); + + cleanup: + dns_test_end(); + return (result); +} + +void +dns_test_end(void) { + if (dst_active) { + dst_lib_destroy(); + dst_active = false; + } + if (hash_active) { + isc_hash_destroy(); + hash_active = false; + } + if (ectx != NULL) + isc_entropy_detach(&ectx); + + cleanup_managers(); + + if (lctx != NULL) + isc_log_destroy(&lctx); + + if (mctx != NULL) + isc_mem_destroy(&mctx); +} + +/* + * Create a view. + */ +isc_result_t +dns_test_makeview(const char *name, dns_view_t **viewp) { + isc_result_t result; + dns_view_t *view = NULL; + + CHECK(dns_view_create(mctx, dns_rdataclass_in, name, &view)); + *viewp = view; + + return (ISC_R_SUCCESS); + + cleanup: + if (view != NULL) + dns_view_detach(&view); + return (result); +} + +isc_result_t +dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view, + bool createview) +{ + dns_fixedname_t fixed_origin; + dns_zone_t *zone = NULL; + isc_result_t result; + dns_name_t *origin; + + REQUIRE(view == NULL || !createview); + + /* + * Create the zone structure. + */ + result = dns_zone_create(&zone, mctx); + if (result != ISC_R_SUCCESS) { + return (result); + } + + /* + * Set zone type and origin. + */ + dns_zone_settype(zone, dns_zone_master); + origin = dns_fixedname_initname(&fixed_origin); + result = dns_name_fromstring(origin, name, 0, NULL); + if (result != ISC_R_SUCCESS) { + goto detach_zone; + } + result = dns_zone_setorigin(zone, origin); + if (result != ISC_R_SUCCESS) { + goto detach_zone; + } + + /* + * If requested, create a view. + */ + if (createview) { + result = dns_test_makeview("view", &view); + if (result != ISC_R_SUCCESS) { + goto detach_zone; + } + } + + /* + * If a view was passed as an argument or created above, attach the + * created zone to it. Otherwise, set the zone's class to IN. + */ + if (view != NULL) { + dns_zone_setview(zone, view); + dns_zone_setclass(zone, view->rdclass); + dns_view_addzone(view, zone); + } else { + dns_zone_setclass(zone, dns_rdataclass_in); + } + + *zonep = zone; + + return (ISC_R_SUCCESS); + + detach_zone: + dns_zone_detach(&zone); + + return (result); +} + +isc_result_t +dns_test_setupzonemgr(void) { + isc_result_t result; + REQUIRE(zonemgr == NULL); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr, + &zonemgr); + return (result); +} + +isc_result_t +dns_test_managezone(dns_zone_t *zone) { + isc_result_t result; + REQUIRE(zonemgr != NULL); + + result = dns_zonemgr_setsize(zonemgr, 1); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_zonemgr_managezone(zonemgr, zone); + return (result); +} + +void +dns_test_releasezone(dns_zone_t *zone) { + REQUIRE(zonemgr != NULL); + dns_zonemgr_releasezone(zonemgr, zone); +} + +void +dns_test_closezonemgr(void) { + REQUIRE(zonemgr != NULL); + + dns_zonemgr_shutdown(zonemgr); + dns_zonemgr_detach(&zonemgr); +} + +/* + * Sleep for 'usec' microseconds. + */ +void +dns_test_nap(uint32_t usec) { +#ifdef HAVE_NANOSLEEP + struct timespec ts; + + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + nanosleep(&ts, NULL); +#elif HAVE_USLEEP + usleep(usec); +#else + /* + * No fractional-second sleep function is available, so we + * round up to the nearest second and sleep instead + */ + sleep((usec / 1000000) + 1); +#endif +} + +isc_result_t +dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, + const char *testfile) +{ + isc_result_t result; + dns_fixedname_t fixed; + dns_name_t *name; + + name = dns_fixedname_initname(&fixed); + + result = dns_name_fromstring(name, origin, 0, NULL); + if (result != ISC_R_SUCCESS) + return(result); + + result = dns_db_create(mctx, "rbt", name, dbtype, dns_rdataclass_in, + 0, NULL, db); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_db_load(*db, testfile); + return (result); +} + +static int +fromhex(char c) { + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'a' && c <= 'f') + return (c - 'a' + 10); + else if (c >= 'A' && c <= 'F') + return (c - 'A' + 10); + + printf("bad input format: %02x\n", c); + exit(3); + /* NOTREACHED */ +} + +/* + * Format contents of given memory region as a hex string, using the buffer + * of length 'buflen' pointed to by 'buf'. 'buflen' must be at least three + * times 'len'. Always returns 'buf'. + */ +char * +dns_test_tohex(const unsigned char *data, size_t len, char *buf, size_t buflen) +{ + isc_constregion_t source = { + .base = data, + .length = len + }; + isc_buffer_t target; + isc_result_t result; + + memset(buf, 0, buflen); + isc_buffer_init(&target, buf, buflen); + result = isc_hex_totext((isc_region_t *)&source, 1, " ", &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + return (buf); +} + +isc_result_t +dns_test_getdata(const char *file, unsigned char *buf, + size_t bufsiz, size_t *sizep) +{ + isc_result_t result; + unsigned char *bp; + char *rp, *wp; + char s[BUFSIZ]; + size_t len, i; + FILE *f = NULL; + int n; + + result = isc_stdio_open(file, "r", &f); + if (result != ISC_R_SUCCESS) + return (result); + + bp = buf; + while (fgets(s, sizeof(s), f) != NULL) { + rp = s; + wp = s; + len = 0; + while (*rp != '\0') { + if (*rp == '#') + break; + if (*rp != ' ' && *rp != '\t' && + *rp != '\r' && *rp != '\n') { + *wp++ = *rp; + len++; + } + rp++; + } + if (len == 0U) + continue; + if (len % 2 != 0U) + CHECK(ISC_R_UNEXPECTEDEND); + if (len > bufsiz * 2) + CHECK(ISC_R_NOSPACE); + rp = s; + for (i = 0; i < len; i += 2) { + n = fromhex(*rp++); + n *= 16; + n += fromhex(*rp++); + *bp++ = n; + } + } + + + *sizep = bp - buf; + + result = ISC_R_SUCCESS; + + cleanup: + isc_stdio_close(f); + return (result); +} + +isc_result_t +dns_test_rdatafromstring(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t rdtype, unsigned char *dst, + size_t dstlen, const char *src) +{ + isc_buffer_t source, target; + isc_lex_t *lex = NULL; + isc_result_t result; + size_t length; + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + REQUIRE(dst != NULL); + REQUIRE(src != NULL); + + /* + * Set up source to hold the input string. + */ + length = strlen(src); + isc_buffer_constinit(&source, src, length); + isc_buffer_add(&source, length); + + /* + * Create a lexer as one is required by dns_rdata_fromtext(). + */ + result = isc_lex_create(mctx, 64, &lex); + if (result != ISC_R_SUCCESS) { + return (result); + } + + /* + * Point lexer at source. + */ + result = isc_lex_openbuffer(lex, &source); + if (result != ISC_R_SUCCESS) { + goto destroy_lexer; + } + + /* + * Set up target for storing uncompressed wire form of provided RDATA. + */ + isc_buffer_init(&target, dst, dstlen); + + /* + * Parse input string, determining result. + */ + result = dns_rdata_fromtext(rdata, rdclass, rdtype, lex, dns_rootname, + 0, NULL, &target, NULL); + + destroy_lexer: + isc_lex_destroy(&lex); + + return (result); +} + +void +dns_test_namefromstring(const char *namestr, dns_fixedname_t *fname) { + size_t length; + isc_buffer_t *b = NULL; + isc_result_t result; + dns_name_t *name; + + length = strlen(namestr); + + result = isc_buffer_allocate(mctx, &b, length); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_buffer_putmem(b, (const unsigned char *) namestr, length); + + name = dns_fixedname_initname(fname); + ATF_REQUIRE(name != NULL); + result = dns_name_fromtext(name, b, dns_rootname, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_buffer_free(&b); +} + +isc_result_t +dns_test_difffromchanges(dns_diff_t *diff, const zonechange_t *changes) { + isc_result_t result = ISC_R_SUCCESS; + unsigned char rdata_buf[1024]; + dns_difftuple_t *tuple = NULL; + isc_consttextregion_t region; + dns_rdatatype_t rdatatype; + dns_fixedname_t fixedname; + dns_rdata_t rdata; + dns_name_t *name; + size_t i; + + REQUIRE(diff != NULL); + REQUIRE(changes != NULL); + + dns_diff_init(mctx, diff); + + for (i = 0; changes[i].owner != NULL; i++) { + /* + * Parse owner name. + */ + name = dns_fixedname_initname(&fixedname); + result = dns_name_fromstring(name, changes[i].owner, 0, mctx); + if (result != ISC_R_SUCCESS) { + break; + } + + /* + * Parse RDATA type. + */ + region.base = changes[i].type; + region.length = strlen(changes[i].type); + result = dns_rdatatype_fromtext(&rdatatype, + (isc_textregion_t *)®ion); + if (result != ISC_R_SUCCESS) { + break; + } + + /* + * Parse RDATA. + */ + dns_rdata_init(&rdata); + result = dns_test_rdatafromstring(&rdata, dns_rdataclass_in, + rdatatype, rdata_buf, + sizeof(rdata_buf), + changes[i].rdata); + if (result != ISC_R_SUCCESS) { + break; + } + + /* + * Create a diff tuple for the parsed change and append it to + * the diff. + */ + result = dns_difftuple_create(mctx, changes[i].op, name, + changes[i].ttl, &rdata, &tuple); + if (result != ISC_R_SUCCESS) { + break; + } + dns_diff_append(diff, &tuple); + } + + if (result != ISC_R_SUCCESS) { + dns_diff_clear(diff); + } + + return (result); +} diff --git a/lib/dns/tests/dnstest.h b/lib/dns/tests/dnstest.h new file mode 100644 index 0000000..ebbca6c --- /dev/null +++ b/lib/dns/tests/dnstest.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <inttypes.h> +#include <stdbool.h> + +#include <isc/buffer.h> +#include <isc/entropy.h> +#include <isc/hash.h> +#include <isc/log.h> +#include <isc/mem.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/diff.h> +#include <dns/result.h> +#include <dns/zone.h> + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +typedef struct { + dns_diffop_t op; + const char *owner; + dns_ttl_t ttl; + const char *type; + const char *rdata; +} zonechange_t; + +#define ZONECHANGE_SENTINEL { 0, NULL, 0, NULL, NULL } + +extern isc_mem_t *mctx; +extern isc_entropy_t *ectx; +extern isc_log_t *lctx; +extern isc_taskmgr_t *taskmgr; +extern isc_task_t *maintask; +extern isc_timermgr_t *timermgr; +extern isc_socketmgr_t *socketmgr; +extern dns_zonemgr_t *zonemgr; +extern bool app_running; +extern int ncpus; +extern bool debug_mem_record; + +isc_result_t +dns_test_begin(FILE *logfile, bool create_managers); + +void +dns_test_end(void); + +isc_result_t +dns_test_makeview(const char *name, dns_view_t **viewp); + +/*% + * Create a zone with origin 'name', return a pointer to the zone object in + * 'zonep'. + * + * If 'view' is set, the returned zone will be assigned to the passed view. + * 'createview' must be set to false when 'view' is non-NULL. + * + * If 'view' is not set and 'createview' is true, a new view is also created + * and the returned zone is assigned to it. This imposes two requirements on + * the caller: 1) the returned zone has to be subsequently assigned to a zone + * manager, otherwise its cleanup will fail, 2) the created view has to be + * cleaned up by the caller. + * + * If 'view' is not set and 'createview' is false, the returned zone will not + * be assigned to any view. + */ +isc_result_t +dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view, + bool createview); + +isc_result_t +dns_test_setupzonemgr(void); + +isc_result_t +dns_test_managezone(dns_zone_t *zone); + +void +dns_test_releasezone(dns_zone_t *zone); + +void +dns_test_closezonemgr(void); + +void +dns_test_nap(uint32_t usec); + +isc_result_t +dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, + const char *testfile); + +isc_result_t +dns_test_getdata(const char *file, unsigned char *buf, + size_t bufsiz, size_t *sizep); + +char * +dns_test_tohex(const unsigned char *data, size_t len, char *buf, size_t buflen); + +/*% + * Try parsing text form RDATA in "src" (of class "rdclass" and type "rdtype") + * into a structure representing that RDATA at "rdata", storing the + * uncompressed wire form of that RDATA at "dst", which is "dstlen" bytes long. + */ +isc_result_t +dns_test_rdatafromstring(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t rdtype, unsigned char *dst, + size_t dstlen, const char *src); + +void +dns_test_namefromstring(const char *namestr, dns_fixedname_t *fname); + +/*% + * Given a pointer to an uninitialized dns_diff_t structure in 'diff', make it + * contain diff tuples representing zone database changes listed in 'changes'. + */ +isc_result_t +dns_test_difffromchanges(dns_diff_t *diff, const zonechange_t *changes); diff --git a/lib/dns/tests/dst_test.c b/lib/dns/tests/dst_test.c new file mode 100644 index 0000000..421ab2f --- /dev/null +++ b/lib/dns/tests/dst_test.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdbool.h> +#include <unistd.h> + +#include <isc/file.h> +#include <isc/util.h> +#include <isc/stdio.h> +#include <isc/string.h> + +#include <dst/dst.h> +#include <dst/result.h> + +#include "../dst_internal.h" + +#include "dnstest.h" + +ATF_TC(sig); +ATF_TC_HEAD(sig, tc) { + atf_tc_set_md_var(tc, "descr", "signature ineffability"); +} + +/* + * Read sig in file at path to buf. + */ +static isc_result_t +sig_fromfile(const char *path, isc_buffer_t *buf) { + isc_result_t result; + size_t rval, len; + FILE *fp = NULL; + unsigned char val; + char *p, *data; + off_t size; + + result = isc_stdio_open(path, "rb", &fp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_file_getsizefd(fileno(fp), &size); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + data = isc_mem_get(mctx, (size + 1)); + ATF_REQUIRE(data != NULL); + + len = (size_t)size; + p = data; + while (len != 0U) { + result = isc_stdio_read(p, 1, len, fp, &rval); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + len -= rval; + p += rval; + } + isc_stdio_close(fp); + + p = data; + len = size; + while (len > 0U) { + if ((*p == '\r') || (*p == '\n')) { + ++p; + --len; + continue; + } else if (len < 2U) + goto err; + if (('0' <= *p) && (*p <= '9')) { + val = *p - '0'; + } else if (('A' <= *p) && (*p <= 'F')) { + val = *p - 'A' + 10; + } else { + result = ISC_R_BADHEX; + goto err; + } + ++p; + val <<= 4; + --len; + if (('0' <= *p) && (*p <= '9')) { + val |= (*p - '0'); + } else if (('A' <= *p) && (*p <= 'F')) { + val |= (*p - 'A' + 10); + } else { + result = ISC_R_BADHEX; + goto err; + } + ++p; + --len; + isc_buffer_putuint8(buf, val); + } + + result = ISC_R_SUCCESS; + + err: + isc_mem_put(mctx, data, size + 1); + return (result); +} + +static void +check_sig(const char *datapath, const char *sigpath, const char *keyname, + dns_keytag_t id, dns_secalg_t alg, int type, bool expect) +{ + isc_result_t result; + size_t rval, len; + FILE *fp; + dst_key_t *key = NULL; + unsigned char sig[512]; + unsigned char *p; + unsigned char *data; + off_t size; + isc_buffer_t b; + isc_buffer_t databuf, sigbuf; + isc_region_t datareg, sigreg; + dns_fixedname_t fname; + dns_name_t *name; + dst_context_t *ctx = NULL; + + /* + * Read data from file in a form usable by dst_verify. + */ + result = isc_stdio_open(datapath, "rb", &fp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_file_getsizefd(fileno(fp), &size); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + data = isc_mem_get(mctx, (size + 1)); + ATF_REQUIRE(data != NULL); + + p = data; + len = (size_t)size; + do { + result = isc_stdio_read(p, 1, len, fp, &rval); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + len -= rval; + p += rval; + } while (len); + isc_stdio_close(fp); + + /* + * Read key from file in a form usable by dst_verify. + */ + name = dns_fixedname_initname(&fname); + isc_buffer_constinit(&b, keyname, strlen(keyname)); + isc_buffer_add(&b, strlen(keyname)); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dst_key_fromfile(name, id, alg, type, "testdata/dst", + mctx, &key); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_buffer_init(&databuf, data, (unsigned int)size); + isc_buffer_add(&databuf, (unsigned int)size); + isc_buffer_usedregion(&databuf, &datareg); + + memset(sig, 0, sizeof(sig)); + isc_buffer_init(&sigbuf, sig, sizeof(sig)); + + /* + * Read precomputed signature from file in a form usable by dst_verify. + */ + result = sig_fromfile(sigpath, &sigbuf); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Verify that the key signed the data. + */ + isc_buffer_remainingregion(&sigbuf, &sigreg); + + result = dst_context_create3(key, mctx, DNS_LOGCATEGORY_GENERAL, + false, &ctx); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dst_context_adddata(ctx, &datareg); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dst_context_verify(ctx, &sigreg); + + ATF_REQUIRE((expect && (result == ISC_R_SUCCESS)) || + (!expect && (result != ISC_R_SUCCESS))); + + + isc_mem_put(mctx, data, size + 1); + dst_context_destroy(&ctx); + dst_key_free(&key); + + return; +} + +ATF_TC_BODY(sig, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + struct { + const char *datapath; + const char *sigpath; + const char *keyname; + dns_keytag_t keyid; + dns_secalg_t alg; + bool expect; + } testcases[] = { + { + "testdata/dst/test1.data", + "testdata/dst/test1.dsasig", + "test.", 23616, DST_ALG_DSA, true + }, + { + "testdata/dst/test1.data", + "testdata/dst/test1.rsasig", + "test.", 54622, DST_ALG_RSAMD5, true + }, + { + /* wrong sig */ + "testdata/dst/test1.data", + "testdata/dst/test1.dsasig", + "test.", 54622, DST_ALG_RSAMD5, false + }, + { + /* wrong data */ + "testdata/dst/test2.data", + "testdata/dst/test1.dsasig", + "test.", 23616, DST_ALG_DSA, false + }, + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) { + if (!dst_algorithm_supported(testcases[i].alg)) { + continue; + } + + check_sig(testcases[i].datapath, + testcases[i].sigpath, + testcases[i].keyname, + testcases[i].keyid, + testcases[i].alg, + DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, + testcases[i].expect); + } + + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, sig); + + return (atf_no_error()); +} diff --git a/lib/dns/tests/geoip_test.c b/lib/dns/tests/geoip_test.c new file mode 100644 index 0000000..4e8a5f0 --- /dev/null +++ b/lib/dns/tests/geoip_test.c @@ -0,0 +1,711 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdbool.h> +#include <unistd.h> + +#include <isc/print.h> +#include <isc/string.h> +#include <isc/types.h> + +#include <dns/geoip.h> + +#include "dnstest.h" + +#ifdef HAVE_GEOIP +#include <GeoIP.h> + +/* We use GeoIP databases from the 'geoip' system test */ +#define TEST_GEOIP_DATA "../../../bin/tests/system/geoip/data" + +/* + * Helper functions + * (Mostly copied from bin/named/geoip.c) + */ +static dns_geoip_databases_t geoip = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static void +init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback, + GeoIPOptions method, const char *name) +{ + char *info; + GeoIP *db; + + REQUIRE(dbp != NULL); + + db = *dbp; + + if (db != NULL) { + GeoIP_delete(db); + db = *dbp = NULL; + } + + if (! GeoIP_db_avail(edition)) { + fprintf(stderr, "GeoIP %s (type %d) DB not available\n", + name, edition); + goto fail; + } + + fprintf(stderr, "initializing GeoIP %s (type %d) DB\n", + name, edition); + + db = GeoIP_open_type(edition, method); + if (db == NULL) { + fprintf(stderr, + "failed to initialize GeoIP %s (type %d) DB%s\n", + name, edition, fallback == 0 + ? "; geoip matches using this database will fail" + : ""); + goto fail; + } + + info = GeoIP_database_info(db); + if (info != NULL) + fprintf(stderr, "%s\n", info); + + *dbp = db; + return; + + fail: + if (fallback != 0) + init_geoip_db(dbp, fallback, 0, method, name); +} + +static void +load_geoip(const char *dir) { + GeoIPOptions method; + +#ifdef _WIN32 + method = GEOIP_STANDARD; +#else + method = GEOIP_MMAP_CACHE; +#endif + + if (dir != NULL) { + char *p; + DE_CONST(dir, p); + GeoIP_setup_custom_directory(p); + } + + init_geoip_db(&geoip.country_v4, GEOIP_COUNTRY_EDITION, 0, + method, "Country (IPv4)"); +#ifdef HAVE_GEOIP_V6 + init_geoip_db(&geoip.country_v6, GEOIP_COUNTRY_EDITION_V6, 0, + method, "Country (IPv6)"); +#endif + + init_geoip_db(&geoip.city_v4, GEOIP_CITY_EDITION_REV1, + GEOIP_CITY_EDITION_REV0, method, "City (IPv4)"); +#if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6) + init_geoip_db(&geoip.city_v6, GEOIP_CITY_EDITION_REV1_V6, + GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)"); +#endif + + init_geoip_db(&geoip.region, GEOIP_REGION_EDITION_REV1, + GEOIP_REGION_EDITION_REV0, method, "Region"); + init_geoip_db(&geoip.isp, GEOIP_ISP_EDITION, 0, + method, "ISP"); + init_geoip_db(&geoip.org, GEOIP_ORG_EDITION, 0, + method, "Org"); + init_geoip_db(&geoip.as, GEOIP_ASNUM_EDITION, 0, + method, "AS"); + init_geoip_db(&geoip.domain, GEOIP_DOMAIN_EDITION, 0, + method, "Domain"); + init_geoip_db(&geoip.netspeed, GEOIP_NETSPEED_EDITION, 0, + method, "NetSpeed"); +} + +static bool +do_lookup_string(const char *addr, uint8_t *scope, + dns_geoip_subtype_t subtype, const char *string) +{ + dns_geoip_elem_t elt; + struct in_addr in4; + isc_netaddr_t na; + + inet_pton(AF_INET, addr, &in4); + isc_netaddr_fromin(&na, &in4); + + elt.subtype = subtype; + strlcpy(elt.as_string, string, sizeof(elt.as_string)); + + return (dns_geoip_match(&na, scope, &geoip, &elt)); +} + +static bool +do_lookup_string_v6(const char *addr, uint8_t *scope, + dns_geoip_subtype_t subtype, const char *string) +{ + dns_geoip_elem_t elt; + struct in6_addr in6; + isc_netaddr_t na; + + inet_pton(AF_INET6, addr, &in6); + isc_netaddr_fromin6(&na, &in6); + + elt.subtype = subtype; + strlcpy(elt.as_string, string, sizeof(elt.as_string)); + + return (dns_geoip_match(&na, scope, &geoip, &elt)); +} + +static bool +do_lookup_int(const char *addr, uint8_t *scope, + dns_geoip_subtype_t subtype, int id) +{ + dns_geoip_elem_t elt; + struct in_addr in4; + isc_netaddr_t na; + + inet_pton(AF_INET, addr, &in4); + isc_netaddr_fromin(&na, &in4); + + elt.subtype = subtype; + elt.as_int = id; + + return (dns_geoip_match(&na, scope, &geoip, &elt)); +} + +/* + * Individual unit tests + */ + +/* GeoIP country matching */ +ATF_TC(country); +ATF_TC_HEAD(country, tc) { + atf_tc_set_md_var(tc, "descr", "test country database matching"); +} +ATF_TC_BODY(country, tc) { + isc_result_t result; + bool match; + uint8_t scope; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.country_v4 == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.1", &scope, + dns_geoip_country_code, "AU"); + ATF_CHECK(match); + ATF_CHECK_EQ(scope, 32); + + match = do_lookup_string("10.53.0.1", &scope, + dns_geoip_country_code3, "AUS"); + ATF_CHECK(match); + ATF_CHECK_EQ(scope, 32); + + match = do_lookup_string("10.53.0.1", &scope, + dns_geoip_country_name, "Australia"); + ATF_CHECK(match); + ATF_CHECK_EQ(scope, 32); + + match = do_lookup_string("192.0.2.128", &scope, + dns_geoip_country_code, "O1"); + ATF_CHECK(match); + ATF_CHECK_EQ(scope, 24); + + match = do_lookup_string("192.0.2.128", &scope, + dns_geoip_country_name, "Other"); + ATF_CHECK(match); + ATF_CHECK_EQ(scope, 24); + + dns_test_end(); +} + +/* GeoIP country (ipv6) matching */ +ATF_TC(country_v6); +ATF_TC_HEAD(country_v6, tc) { + atf_tc_set_md_var(tc, "descr", "test country (ipv6) database matching"); +} +ATF_TC_BODY(country_v6, tc) { + isc_result_t result; + bool match; + uint8_t scope; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.country_v6 == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope, + dns_geoip_country_code, "AU"); + ATF_CHECK(match); + ATF_CHECK_EQ(scope, 128); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope, + dns_geoip_country_code3, "AUS"); + ATF_CHECK(match); + ATF_CHECK_EQ(scope, 128); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope, + dns_geoip_country_name, "Australia"); + ATF_CHECK(match); + ATF_CHECK_EQ(scope, 128); + + dns_test_end(); +} + +/* GeoIP city (ipv4) matching */ +ATF_TC(city); +ATF_TC_HEAD(city, tc) { + atf_tc_set_md_var(tc, "descr", "test city database matching"); +} +ATF_TC_BODY(city, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.city_v4 == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_city_continentcode, "NA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_city_countrycode, "US"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_city_countrycode3, "USA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_city_countryname, "United States"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_city_region, "CA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_city_regionname, "California"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_city_name, "Redwood City"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_city_postalcode, "94063"); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.1", NULL, dns_geoip_city_areacode, 650); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.1", NULL, dns_geoip_city_metrocode, 807); + ATF_CHECK(match); + + dns_test_end(); +} + +/* GeoIP city (ipv6) matching */ +ATF_TC(city_v6); +ATF_TC_HEAD(city_v6, tc) { + atf_tc_set_md_var(tc, "descr", "test city (ipv6) database matching"); +} +ATF_TC_BODY(city_v6, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.city_v6 == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL, + dns_geoip_city_continentcode, "NA"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL, + dns_geoip_city_countrycode, "US"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL, + dns_geoip_city_countrycode3, "USA"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL, + dns_geoip_city_countryname, + "United States"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL, + dns_geoip_city_region, "CA"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL, + dns_geoip_city_regionname, "California"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL, + dns_geoip_city_name, "Redwood City"); + ATF_CHECK(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL, + dns_geoip_city_postalcode, "94063"); + ATF_CHECK(match); + + dns_test_end(); +} + + +/* GeoIP region matching */ +ATF_TC(region); +ATF_TC_HEAD(region, tc) { + atf_tc_set_md_var(tc, "descr", "test region database matching"); +} +ATF_TC_BODY(region, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.region == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_region_code, "CA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_region_name, "California"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.1", NULL, + dns_geoip_region_countrycode, "US"); + ATF_CHECK(match); + + dns_test_end(); +} + +/* + * GeoIP best-database matching + * (With no specified databse and a city database available, answers + * should come from city database. With city database unavailable, region + * database. Region database unavailable, country database.) + */ +ATF_TC(best); +ATF_TC_HEAD(best, tc) { + atf_tc_set_md_var(tc, "descr", "test best database matching"); +} +ATF_TC_BODY(best, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.region == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countrycode, "US"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countrycode3, "USA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countryname, "United States"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_regionname, "Virginia"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_region, "VA"); + ATF_CHECK(match); + + GeoIP_delete(geoip.city_v4); + geoip.city_v4 = NULL; + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countrycode, "AU"); + ATF_CHECK(match); + + /* + * Note, region doesn't support code3 or countryname, so + * the next two would be answered from the country database instead + */ + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countrycode3, "CAN"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countryname, "Canada"); + ATF_CHECK(match); + + GeoIP_delete(geoip.region); + geoip.region = NULL; + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countrycode, "CA"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countrycode3, "CAN"); + ATF_CHECK(match); + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_countryname, "Canada"); + ATF_CHECK(match); + + dns_test_end(); +} + + +/* GeoIP asnum matching */ +ATF_TC(asnum); +ATF_TC_HEAD(asnum, tc) { + atf_tc_set_md_var(tc, "descr", "test asnum database matching"); +} +ATF_TC_BODY(asnum, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.as == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + + match = do_lookup_string("10.53.0.3", NULL, dns_geoip_as_asnum, + "AS100003 Three Network Labs"); + ATF_CHECK(match); + + dns_test_end(); +} + +/* GeoIP isp matching */ +ATF_TC(isp); +ATF_TC_HEAD(isp, tc) { + atf_tc_set_md_var(tc, "descr", "test isp database matching"); +} +ATF_TC_BODY(isp, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.isp == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.1", NULL, dns_geoip_isp_name, + "One Systems, Inc."); + ATF_CHECK(match); + + dns_test_end(); +} + +/* GeoIP org matching */ +ATF_TC(org); +ATF_TC_HEAD(org, tc) { + atf_tc_set_md_var(tc, "descr", "test org database matching"); +} +ATF_TC_BODY(org, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.org == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.2", NULL, dns_geoip_org_name, + "Two Technology Ltd."); + ATF_CHECK(match); + + dns_test_end(); +} + +/* GeoIP domain matching */ +ATF_TC(domain); +ATF_TC_HEAD(domain, tc) { + atf_tc_set_md_var(tc, "descr", "test domain database matching"); +} +ATF_TC_BODY(domain, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.domain == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_string("10.53.0.4", NULL, + dns_geoip_domain_name, "four.com"); + ATF_CHECK(match); + + dns_test_end(); +} + +/* GeoIP netspeed matching */ +ATF_TC(netspeed); +ATF_TC_HEAD(netspeed, tc) { + atf_tc_set_md_var(tc, "descr", "test netspeed database matching"); +} +ATF_TC_BODY(netspeed, tc) { + isc_result_t result; + bool match; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + if (geoip.netspeed == NULL) { + dns_test_end(); + atf_tc_skip("Database not available"); + } + + match = do_lookup_int("10.53.0.1", NULL, dns_geoip_netspeed_id, 0); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.2", NULL, dns_geoip_netspeed_id, 1); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.3", NULL, dns_geoip_netspeed_id, 2); + ATF_CHECK(match); + + match = do_lookup_int("10.53.0.4", NULL, dns_geoip_netspeed_id, 3); + ATF_CHECK(match); + + dns_test_end(); +} +#else +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping geoip test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("GeoIP not available"); +} +#endif + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { +#ifdef HAVE_GEOIP + ATF_TP_ADD_TC(tp, country); + ATF_TP_ADD_TC(tp, country_v6); + ATF_TP_ADD_TC(tp, city); + ATF_TP_ADD_TC(tp, city_v6); + ATF_TP_ADD_TC(tp, region); + ATF_TP_ADD_TC(tp, best); + ATF_TP_ADD_TC(tp, asnum); + ATF_TP_ADD_TC(tp, isp); + ATF_TP_ADD_TC(tp, org); + ATF_TP_ADD_TC(tp, domain); + ATF_TP_ADD_TC(tp, netspeed); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + + return (atf_no_error()); +} diff --git a/lib/dns/tests/gost_test.c b/lib/dns/tests/gost_test.c new file mode 100644 index 0000000..204c6cc --- /dev/null +++ b/lib/dns/tests/gost_test.c @@ -0,0 +1,379 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* ! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdio.h> +#include <string.h> + +#include <isc/util.h> +#include <isc/print.h> +#include <isc/string.h> + +#include "dnstest.h" + +#ifdef HAVE_OPENSSL_GOST +#include "../dst_gost.h" +#include <openssl/err.h> +#include <openssl/objects.h> +#include <openssl/rsa.h> +#include <openssl/engine.h> +#include <openssl/bn.h> +#endif + +#ifdef HAVE_PKCS11_GOST +#include "../dst_gost.h" +#include <pk11/internal.h> +#define WANT_GOST_PARAMS +#include <pk11/constants.h> +#include <pkcs11/pkcs11.h> +#endif + +#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) +/* + * Test data from Wikipedia GOST (hash function) + */ + +unsigned char digest[ISC_GOST_DIGESTLENGTH]; +unsigned char buffer[1024]; +const char *s; +char str[2 * ISC_GOST_DIGESTLENGTH + 3]; +int i = 0; + +/* + * Precondition: a hexadecimal number in *d, the length of that number in len, + * and a pointer to a character array to put the output (*out). + * Postcondition: A String representation of the given hexadecimal number is + * placed into the array *out + * + * 'out' MUST point to an array of at least len * 2 + 1 + * + * Return values: ISC_R_SUCCESS if the operation is sucessful + */ +static isc_result_t +tohexstr(unsigned char *d, unsigned int len, char *out, size_t out_size) { + char c_ret[] = "AA"; + unsigned int j; + + out[0] = '\0'; + strlcat(out, "0x", out_size); + for (j = 0; j < len; j++) { + snprintf(c_ret, sizeof(c_ret), "%02X", d[j]); + strlcat(out, c_ret, out_size); + } + return (ISC_R_SUCCESS); +} + + +#define TEST_INPUT(x) (x), sizeof(x)-1 + +typedef struct hash_testcase { + const char *input; + size_t input_len; + const char *result; + int repeats; +} hash_testcase_t; + +ATF_TC(isc_gost_md); +ATF_TC_HEAD(isc_gost_md, tc) { + atf_tc_set_md_var(tc, "descr", + "GOST R 34.11-94 examples from Wikipedia"); +} +ATF_TC_BODY(isc_gost_md, tc) { + isc_gost_t gost; + isc_result_t result; + + UNUSED(tc); + + /* + * These are the various test vectors. All of these are passed + * through the hash function and the results are compared to the + * result specified here. + */ + hash_testcase_t testcases[] = { + /* Test 1 */ + { + TEST_INPUT(""), + "0x981E5F3CA30C841487830F84FB433E1" + "3AC1101569B9C13584AC483234CD656C0", + 1 + }, + /* Test 2 */ + { + TEST_INPUT("a"), + "0xE74C52DD282183BF37AF0079C9F7805" + "5715A103F17E3133CEFF1AACF2F403011", + 1 + }, + /* Test 3 */ + { + TEST_INPUT("abc"), + "0xB285056DBF18D7392D7677369524DD1" + "4747459ED8143997E163B2986F92FD42C", + 1 + }, + /* Test 4 */ + { + TEST_INPUT("message digest"), + "0xBC6041DD2AA401EBFA6E9886734174F" + "EBDB4729AA972D60F549AC39B29721BA0", + 1 + }, + /* Test 5 */ + { + TEST_INPUT("The quick brown fox jumps " + "over the lazy dog"), + "0x9004294A361A508C586FE53D1F1B027" + "46765E71B765472786E4770D565830A76", + 1 + }, + + /* Test 6 */ + { + TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" + "fghijklmnopqrstuvwxyz0123456789"), + "0x73B70A39497DE53A6E08C67B6D4DB85" + "3540F03E9389299D9B0156EF7E85D0F61", + 1 + }, + /* Test 7 */ + { + TEST_INPUT("1234567890123456789012345678901" + "2345678901234567890123456789012" + "345678901234567890"), + "0x6BC7B38989B28CF93AE8842BF9D7529" + "05910A7528A61E5BCE0782DE43E610C90", + 1 + }, + /* Test 8 */ + { + TEST_INPUT("This is message, length=32 bytes"), + "0x2CEFC2F7B7BDC514E18EA57FA74FF35" + "7E7FA17D652C75F69CB1BE7893EDE48EB", + 1 + }, + /* Test 9 */ + { + TEST_INPUT("Suppose the original message " + "has length = 50 bytes"), + "0xC3730C5CBCCACF915AC292676F21E8B" + "D4EF75331D9405E5F1A61DC3130A65011", + 1 + }, + /* Test 10 */ + { + TEST_INPUT("U") /* times 128 */, + "0x1C4AC7614691BBF427FA2316216BE8F" + "10D92EDFD37CD1027514C1008F649C4E8", + 128 + }, + /* Test 11 */ + { + TEST_INPUT("a") /* times 1000000 */, + "0x8693287AA62F9478F7CB312EC0866B6" + "C4E4A0F11160441E8F4FFCD2715DD554F", + 1000000 + }, + { NULL, 0, NULL, 1 } + }; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + hash_testcase_t *testcase = testcases; + + while (testcase->input != NULL && testcase->result != NULL) { + result = isc_gost_init(&gost); + ATF_REQUIRE(result == ISC_R_SUCCESS); + for(i = 0; i < testcase->repeats; i++) { + result = isc_gost_update(&gost, + (const uint8_t *) testcase->input, + testcase->input_len); + ATF_REQUIRE(result == ISC_R_SUCCESS); + } + result = isc_gost_final(&gost, digest); + ATF_REQUIRE(result == ISC_R_SUCCESS); + tohexstr(digest, ISC_GOST_DIGESTLENGTH, str, sizeof(str)); + ATF_CHECK_STREQ(str, testcase->result); + + testcase++; + } + + dns_test_end(); +} + +ATF_TC(isc_gost_private); +ATF_TC_HEAD(isc_gost_private, tc) { + atf_tc_set_md_var(tc, "descr", "GOST R 34.10-2001 private key"); +} +ATF_TC_BODY(isc_gost_private, tc) { + isc_result_t result; + unsigned char privraw[31] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e + }; +#ifdef HAVE_OPENSSL_GOST + unsigned char rbuf[32]; + unsigned char privasn1[70] = { + 0x30, 0x44, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06, + 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30, + 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, + 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, + 0x02, 0x1e, 0x01, 0x04, 0x21, 0x02, 0x1f, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e + }; + unsigned char abuf[71]; + unsigned char gost_dummy_key[71] = { + 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06, + 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30, + 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, + 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, + 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20, 0x1b, + 0x3f, 0x94, 0xf7, 0x1a, 0x5f, 0x2f, 0xe7, 0xe5, + 0x74, 0x0b, 0x8c, 0xd4, 0xb7, 0x18, 0xdd, 0x65, + 0x68, 0x26, 0xd1, 0x54, 0xfb, 0x77, 0xba, 0x63, + 0x72, 0xd9, 0xf0, 0x63, 0x87, 0xe0, 0xd6 + }; + EVP_PKEY *pkey; + EC_KEY *eckey; + BIGNUM *privkey; + const BIGNUM *privkey1; + const unsigned char *p; + int len; + unsigned char *q; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* raw parse */ + privkey = BN_bin2bn(privraw, (int) sizeof(privraw), NULL); + ATF_REQUIRE(privkey != NULL); + p = gost_dummy_key; + pkey = NULL; + ATF_REQUIRE(d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, + (long) sizeof(gost_dummy_key)) != NULL); + ATF_REQUIRE(pkey != NULL); + ATF_REQUIRE(EVP_PKEY_bits(pkey) == 256); + eckey = EVP_PKEY_get0(pkey); + ATF_REQUIRE(eckey != NULL); + ATF_REQUIRE(EC_KEY_set_private_key(eckey, privkey) == 1); + BN_clear_free(privkey); + + /* asn1 tofile */ + len = i2d_PrivateKey(pkey, NULL); + ATF_REQUIRE(len == 70); + q = abuf; + ATF_REQUIRE(i2d_PrivateKey(pkey, &q) == len); + ATF_REQUIRE(memcmp(abuf, privasn1, len) == 0); + EVP_PKEY_free(pkey); + + /* asn1 parse */ + p = privasn1; + pkey = NULL; + ATF_REQUIRE(d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, + (long) len) != NULL); + ATF_REQUIRE(pkey != NULL); + eckey = EVP_PKEY_get0(pkey); + ATF_REQUIRE(eckey != NULL); + privkey1 = EC_KEY_get0_private_key(eckey); + len = BN_num_bytes(privkey1); + ATF_REQUIRE(len == 31); + ATF_REQUIRE(BN_bn2bin(privkey1, rbuf) == len); + ATF_REQUIRE(memcmp(rbuf, privraw, len) == 0); + + dns_test_end(); +#else + CK_BBOOL truevalue = TRUE; + CK_BBOOL falsevalue = FALSE; + CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; + CK_KEY_TYPE keyType = CKK_GOSTR3410; + CK_ATTRIBUTE keyTemplate[] = + { + { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, + { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, + { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, + { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, + { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, + { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, + { CKA_VALUE, privraw, sizeof(privraw) }, + { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset, + (CK_ULONG) sizeof(pk11_gost_a_paramset) }, + { CKA_GOSTR3411_PARAMS, pk11_gost_paramset, + (CK_ULONG) sizeof(pk11_gost_paramset) } + }; + CK_MECHANISM mech = { CKM_GOSTR3410_WITH_GOSTR3411, NULL, 0 }; + CK_BYTE sig[64]; + CK_ULONG siglen; + pk11_context_t pk11_ctx; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE(result == ISC_R_SUCCESS); + + /* create the private key */ + memset(&pk11_ctx, 0, sizeof(pk11_ctx)); + ATF_REQUIRE(pk11_get_session(&pk11_ctx, OP_GOST, true, + false, false, NULL, + pk11_get_best_token(OP_GOST)) == + ISC_R_SUCCESS); + pk11_ctx.object = CK_INVALID_HANDLE; + pk11_ctx.ontoken = false; + ATF_REQUIRE(pkcs_C_CreateObject(pk11_ctx.session, keyTemplate, + (CK_ULONG) 9, &pk11_ctx.object) == + CKR_OK); + ATF_REQUIRE(pk11_ctx.object != CK_INVALID_HANDLE); + + /* sign something */ + ATF_REQUIRE(pkcs_C_SignInit(pk11_ctx.session, &mech, + pk11_ctx.object) == CKR_OK); + siglen = 0; + ATF_REQUIRE(pkcs_C_Sign(pk11_ctx.session, sig, 64, + NULL, &siglen) == CKR_OK); + ATF_REQUIRE(siglen == 64); + ATF_REQUIRE(pkcs_C_Sign(pk11_ctx.session, sig, 64, + sig, &siglen) == CKR_OK); + ATF_REQUIRE(siglen == 64); + + dns_test_end(); +#endif +}; +#else +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping gost test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("GOST not available"); +} +#endif +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { +#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) + ATF_TP_ADD_TC(tp, isc_gost_md); + ATF_TP_ADD_TC(tp, isc_gost_private); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + return (atf_no_error()); +} + diff --git a/lib/dns/tests/keytable_test.c b/lib/dns/tests/keytable_test.c new file mode 100644 index 0000000..ed69fcc --- /dev/null +++ b/lib/dns/tests/keytable_test.c @@ -0,0 +1,622 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdbool.h> +#include <stdio.h> +#include <inttypes.h> +#include <unistd.h> + +#if defined(OPENSSL) || defined(PKCS11CRYPTO) + +#include <isc/base64.h> +#include <isc/buffer.h> +#include <isc/util.h> + +#include <dns/name.h> +#include <dns/fixedname.h> +#include <dns/keytable.h> +#include <dns/nta.h> +#include <dns/rdataclass.h> +#include <dns/rdatastruct.h> +#include <dns/rootns.h> +#include <dns/view.h> + +#include <dst/dst.h> + +#include "dnstest.h" + +dns_keytable_t *keytable = NULL; +dns_ntatable_t *ntatable = NULL; + +static const char *keystr1 = "BQEAAAABok+vaUC9neRv8yeT/FEGgN7svR8s7VBUVSBd8NsAiV8AlaAg O5FHar3JQd95i/puZos6Vi6at9/JBbN8qVmO2AuiXxVqfxMKxIcy+LEB 0Vw4NaSJ3N3uaVREso6aTSs98H/25MjcwLOr7SFfXA7bGhZatLtYY/xu kp6Km5hMfkE="; +static const dns_keytag_t keytag1 = 30591; + +static const char *keystr2 = "BQEAAAABwuHz9Cem0BJ0JQTO7C/a3McR6hMaufljs1dfG/inaJpYv7vH XTrAOm/MeKp+/x6eT4QLru0KoZkvZJnqTI8JyaFTw2OM/ItBfh/hL2lm Cft2O7n3MfeqYtvjPnY7dWghYW4sVfH7VVEGm958o9nfi79532Qeklxh x8pXWdeAaRU="; + +static dns_view_t *view = NULL; + +/* + * Test utilities. In general, these assume input parameters are valid + * (checking with ATF_REQUIRE_EQ, thus aborting if not) and unlikely run time + * errors (such as memory allocation failure) won't happen. This helps keep + * the test code concise. + */ + +/* + * Utility to convert C-string to dns_name_t. Return a pointer to + * static data, and so is not thread safe. + */ +static dns_name_t * +str2name(const char *namestr) { + static dns_fixedname_t fname; + static dns_name_t *name; + static isc_buffer_t namebuf; + void *deconst_namestr; + + name = dns_fixedname_initname(&fname); + DE_CONST(namestr, deconst_namestr); /* OK, since we don't modify it */ + isc_buffer_init(&namebuf, deconst_namestr, strlen(deconst_namestr)); + isc_buffer_add(&namebuf, strlen(namestr)); + ATF_REQUIRE_EQ(dns_name_fromtext(name, &namebuf, dns_rootname, 0, + NULL), ISC_R_SUCCESS); + + return (name); +} + +static void +create_key(uint16_t flags, uint8_t proto, uint8_t alg, + const char *keynamestr, const char *keystr, dst_key_t **target) +{ + dns_rdata_dnskey_t keystruct; + unsigned char keydata[4096]; + isc_buffer_t keydatabuf; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_region_t r; + const dns_rdataclass_t rdclass = dns_rdataclass_in; /* for brevity */ + + keystruct.common.rdclass = rdclass; + keystruct.common.rdtype = dns_rdatatype_dnskey; + keystruct.mctx = NULL; + ISC_LINK_INIT(&keystruct.common, link); + keystruct.flags = flags; + keystruct.protocol = proto; + keystruct.algorithm = alg; + + isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + ATF_REQUIRE_EQ(isc_base64_decodestring(keystr, &keydatabuf), + ISC_R_SUCCESS); + isc_buffer_usedregion(&keydatabuf, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + ATF_REQUIRE_EQ(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, + keystruct.common.rdtype, + &keystruct, &rrdatabuf), + ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(dst_key_fromdns(str2name(keynamestr), rdclass, + &rrdatabuf, mctx, target), + ISC_R_SUCCESS); +} + +/* Common setup: create a keytable and ntatable to test with a few keys */ +static void +create_tables() { + isc_result_t result; + dst_key_t *key = NULL; + isc_stdtime_t now; + + result = dns_test_makeview("view", &view); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(dns_keytable_create(mctx, &keytable), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_ntatable_create(view, taskmgr, timermgr, + &ntatable), ISC_R_SUCCESS); + + /* Add a normal key */ + create_key(257, 3, 5, "example.com", keystr1, &key); + ATF_REQUIRE_EQ(dns_keytable_add(keytable, false, &key), + ISC_R_SUCCESS); + + /* Add a null key */ + ATF_REQUIRE_EQ(dns_keytable_marksecure(keytable, + str2name("null.example")), + ISC_R_SUCCESS); + + /* Add a negative trust anchor, duration 1 hour */ + isc_stdtime_get(&now); + ATF_REQUIRE_EQ(dns_ntatable_add(ntatable, + str2name("insecure.example"), + false, now, 3600), + ISC_R_SUCCESS); +} + +static void +destroy_tables() { + if (ntatable != NULL) + dns_ntatable_detach(&ntatable); + if (keytable != NULL) + dns_keytable_detach(&keytable); + + dns_view_detach(&view); +} + +/* + * Individual unit tests + */ + +ATF_TC(add); +ATF_TC_HEAD(add, tc) { + atf_tc_set_md_var(tc, "descr", "add keys to the keytable"); +} +ATF_TC_BODY(add, tc) { + dst_key_t *key = NULL; + dns_keynode_t *keynode = NULL; + dns_keynode_t *next_keynode = NULL; + dns_keynode_t *null_keynode = NULL; + + UNUSED(tc); + + ATF_REQUIRE_EQ(dns_test_begin(NULL, true), ISC_R_SUCCESS); + create_tables(); + + /* + * Get the keynode for the example.com key. There's no other key for + * the name, so nextkeynode() should return NOTFOUND. + */ + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"), + &keynode), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode, + &next_keynode), ISC_R_NOTFOUND); + + /* + * Try to add the same key. This should have no effect, so + * nextkeynode() should still return NOTFOUND. + */ + create_key(257, 3, 5, "example.com", keystr1, &key); + ATF_REQUIRE_EQ(dns_keytable_add(keytable, false, &key), + ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode, + &next_keynode), ISC_R_NOTFOUND); + + /* Add another key (different keydata) */ + dns_keytable_detachkeynode(keytable, &keynode); + create_key(257, 3, 5, "example.com", keystr2, &key); + ATF_REQUIRE_EQ(dns_keytable_add(keytable, false, &key), + ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"), + &keynode), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode, + &next_keynode), ISC_R_SUCCESS); + dns_keytable_detachkeynode(keytable, &next_keynode); + + /* + * Add a normal key to a name that has a null key. The null key node + * will be updated with the normal key. + */ + dns_keytable_detachkeynode(keytable, &keynode); + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"), + &null_keynode), ISC_R_SUCCESS); + create_key(257, 3, 5, "null.example", keystr2, &key); + ATF_REQUIRE_EQ(dns_keytable_add(keytable, false, &key), + ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"), + &keynode), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(keynode, null_keynode); /* should be the same node */ + ATF_REQUIRE(dns_keynode_key(keynode) != NULL); /* now have a key */ + dns_keytable_detachkeynode(keytable, &null_keynode); + + /* + * Try to add a null key to a name that already has a key. It's + * effectively no-op, so the same key node is still there, with no + * no next node. + * (Note: this and above checks confirm that if a name has a null key + * that's the only key for the name). + */ + ATF_REQUIRE_EQ(dns_keytable_marksecure(keytable, + str2name("null.example")), + ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"), + &null_keynode), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(keynode, null_keynode); + ATF_REQUIRE(dns_keynode_key(keynode) != NULL); + ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode, + &next_keynode), ISC_R_NOTFOUND); + dns_keytable_detachkeynode(keytable, &null_keynode); + + dns_keytable_detachkeynode(keytable, &keynode); + destroy_tables(); + dns_test_end(); +} + +ATF_TC(delete); +ATF_TC_HEAD(delete, tc) { + atf_tc_set_md_var(tc, "descr", "delete keys from the keytable"); +} +ATF_TC_BODY(delete, tc) { + UNUSED(tc); + + ATF_REQUIRE_EQ(dns_test_begin(NULL, true), ISC_R_SUCCESS); + create_tables(); + + /* dns_keytable_delete requires exact match */ + ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.org")), + ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("s.example.com")), + ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.com")), + ISC_R_SUCCESS); + + /* works also for nodes with a null key */ + ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("null.example")), + ISC_R_SUCCESS); + + /* or a negative trust anchor */ + ATF_REQUIRE_EQ(dns_ntatable_delete(ntatable, + str2name("insecure.example")), + ISC_R_SUCCESS); + + destroy_tables(); + dns_test_end(); +} + +ATF_TC(deletekeynode); +ATF_TC_HEAD(deletekeynode, tc) { + atf_tc_set_md_var(tc, "descr", "delete key nodes from the keytable"); +} +ATF_TC_BODY(deletekeynode, tc) { + dst_key_t *key = NULL; + + UNUSED(tc); + + ATF_REQUIRE_EQ(dns_test_begin(NULL, true), ISC_R_SUCCESS); + create_tables(); + + /* key name doesn't match */ + create_key(257, 3, 5, "example.org", keystr1, &key); + ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), + ISC_R_NOTFOUND); + dst_key_free(&key); + + /* subdomain match is the same as no match */ + create_key(257, 3, 5, "sub.example.com", keystr1, &key); + ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), + ISC_R_NOTFOUND); + dst_key_free(&key); + + /* name matches but key doesn't match (resulting in PARTIALMATCH) */ + create_key(257, 3, 5, "example.com", keystr2, &key); + ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), + DNS_R_PARTIALMATCH); + dst_key_free(&key); + + /* + * exact match. after deleting the node the internal rbt node will be + * empty, and any delete or deletekeynode attempt should result in + * NOTFOUND. + */ + create_key(257, 3, 5, "example.com", keystr1, &key); + ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), + ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), + ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.com")), + ISC_R_NOTFOUND); + dst_key_free(&key); + + /* + * A null key node for a name is not deleted when searched by key; + * it must be deleted by dns_keytable_delete() + */ + create_key(257, 3, 5, "null.example", keystr1, &key); + ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), + DNS_R_PARTIALMATCH); + ATF_REQUIRE_EQ(dns_keytable_delete(keytable, dst_key_name(key)), + ISC_R_SUCCESS); + dst_key_free(&key); + + destroy_tables(); + dns_test_end(); +} + +ATF_TC(find); +ATF_TC_HEAD(find, tc) { + atf_tc_set_md_var(tc, "descr", "check find-variant operations"); +} +ATF_TC_BODY(find, tc) { + dns_keynode_t *keynode = NULL; + dns_fixedname_t fname; + dns_name_t *name; + + UNUSED(tc); + + ATF_REQUIRE_EQ(dns_test_begin(NULL, true), ISC_R_SUCCESS); + create_tables(); + + /* + * dns_keytable_find() requires exact name match. It matches node + * that has a null key, too. + */ + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.org"), + &keynode), ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("sub.example.com"), + &keynode), ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"), + &keynode), ISC_R_SUCCESS); + dns_keytable_detachkeynode(keytable, &keynode); + ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"), + &keynode), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_keynode_key(keynode), NULL); + dns_keytable_detachkeynode(keytable, &keynode); + + /* + * dns_keytable_finddeepestmatch() allows partial match. Also match + * nodes with a null key. + */ + name = dns_fixedname_initname(&fname); + ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable, + str2name("example.com"), + name), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_name_equal(name, str2name("example.com")), true); + ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable, + str2name("s.example.com"), + name), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_name_equal(name, str2name("example.com")), true); + ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable, + str2name("example.org"), + name), ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable, + str2name("null.example"), + name), ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dns_name_equal(name, str2name("null.example")), + true); + + /* + * dns_keytable_findkeynode() requires exact name, algorithm, keytag + * match. If algorithm or keytag doesn't match, should result in + * PARTIALMATCH. Same for a node with a null key. + */ + ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, + str2name("example.org"), + 5, keytag1, &keynode), + ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, + str2name("sub.example.com"), + 5, keytag1, &keynode), + ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, + str2name("example.com"), + 4, keytag1, &keynode), + DNS_R_PARTIALMATCH); /* different algorithm */ + ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, + str2name("example.com"), + 5, keytag1 + 1, &keynode), + DNS_R_PARTIALMATCH); /* different keytag */ + ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, + str2name("null.example"), + 5, 0, &keynode), + DNS_R_PARTIALMATCH); /* null key */ + ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, + str2name("example.com"), + 5, keytag1, &keynode), + ISC_R_SUCCESS); /* complete match */ + dns_keytable_detachkeynode(keytable, &keynode); + + destroy_tables(); + dns_test_end(); +} + +ATF_TC(issecuredomain); +ATF_TC_HEAD(issecuredomain, tc) { + atf_tc_set_md_var(tc, "descr", "check issecuredomain()"); +} +ATF_TC_BODY(issecuredomain, tc) { + bool issecure; + const char **n; + const char *names[] = {"example.com", "sub.example.com", + "null.example", "sub.null.example", NULL}; + + UNUSED(tc); + ATF_REQUIRE_EQ(dns_test_begin(NULL, true), ISC_R_SUCCESS); + create_tables(); + + /* + * Domains that are an exact or partial match of a key name are + * considered secure. It's the case even if the key is null + * (validation will then fail, but that's actually the intended effect + * of installing a null key). + */ + for (n = names; *n != NULL; n++) { + ATF_REQUIRE_EQ(dns_keytable_issecuredomain(keytable, + str2name(*n), + NULL, + &issecure), + ISC_R_SUCCESS); + ATF_REQUIRE_EQ(issecure, true); + } + + /* + * If the key table has no entry (not even a null one) for a domain or + * any of its ancestors, that domain is considered insecure. + */ + ATF_REQUIRE_EQ(dns_keytable_issecuredomain(keytable, + str2name("example.org"), + NULL, + &issecure), + ISC_R_SUCCESS); + ATF_REQUIRE_EQ(issecure, false); + + destroy_tables(); + dns_test_end(); +} + +ATF_TC(dump); +ATF_TC_HEAD(dump, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_keytable_dump()"); +} +ATF_TC_BODY(dump, tc) { + UNUSED(tc); + + ATF_REQUIRE_EQ(dns_test_begin(NULL, true), ISC_R_SUCCESS); + create_tables(); + + /* + * Right now, we only confirm the dump attempt doesn't cause disruption + * (so we don't check the dump content). + */ + ATF_REQUIRE_EQ(dns_keytable_dump(keytable, stdout), ISC_R_SUCCESS); + + destroy_tables(); + dns_test_end(); +} + +ATF_TC(nta); +ATF_TC_HEAD(nta, tc) { + atf_tc_set_md_var(tc, "descr", "check negative trust anchors"); +} +ATF_TC_BODY(nta, tc) { + isc_result_t result; + dst_key_t *key = NULL; + bool issecure, covered; + dns_view_t *myview = NULL; + isc_stdtime_t now; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_makeview("view", &myview); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_task_create(taskmgr, 0, &myview->task); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_view_initsecroots(myview, mctx); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_view_getsecroots(myview, &keytable); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_view_initntatable(myview, taskmgr, timermgr); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_view_getntatable(myview, &ntatable); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + create_key(257, 3, 5, "example", keystr1, &key); + result = dns_keytable_add(keytable, false, &key); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_stdtime_get(&now); + result = dns_ntatable_add(ntatable, + str2name("insecure.example"), + false, now, 1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Should be secure */ + result = dns_view_issecuredomain(myview, + str2name("test.secure.example"), + now, true, &issecure); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(issecure); + + /* Should not be secure */ + result = dns_view_issecuredomain(myview, + str2name("test.insecure.example"), + now, true, &issecure); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(!issecure); + + /* NTA covered */ + covered = dns_view_ntacovers(myview, now, str2name("insecure.example"), + dns_rootname); + ATF_CHECK(covered); + + /* Not NTA covered */ + covered = dns_view_ntacovers(myview, now, str2name("secure.example"), + dns_rootname); + ATF_CHECK(!covered); + + /* As of now + 2, the NTA should be clear */ + result = dns_view_issecuredomain(myview, + str2name("test.insecure.example"), + now + 2, true, &issecure); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(issecure); + + /* Now check deletion */ + result = dns_view_issecuredomain(myview, str2name("test.new.example"), + now, true, &issecure); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(issecure); + + result = dns_ntatable_add(ntatable, str2name("new.example"), + false, now, 3600); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_view_issecuredomain(myview, str2name("test.new.example"), + now, true, &issecure); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(!issecure); + + result = dns_ntatable_delete(ntatable, str2name("new.example")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_view_issecuredomain(myview, str2name("test.new.example"), + now, true, &issecure); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(issecure); + + /* Clean up */ + dns_ntatable_detach(&ntatable); + dns_keytable_detach(&keytable); + dns_view_detach(&myview); + + dns_test_end(); +} + +#else +#include <isc/util.h> + +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping keytable test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("DNSSEC not available"); +} +#endif + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { +#if defined(OPENSSL) || defined(PKCS11CRYPTO) + ATF_TP_ADD_TC(tp, add); + ATF_TP_ADD_TC(tp, delete); + ATF_TP_ADD_TC(tp, deletekeynode); + ATF_TP_ADD_TC(tp, find); + ATF_TP_ADD_TC(tp, issecuredomain); + ATF_TP_ADD_TC(tp, dump); + ATF_TP_ADD_TC(tp, nta); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + + return (atf_no_error()); +} diff --git a/lib/dns/tests/master_test.c b/lib/dns/tests/master_test.c new file mode 100644 index 0000000..5cce2f3 --- /dev/null +++ b/lib/dns/tests/master_test.c @@ -0,0 +1,684 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> + +#include <isc/print.h> +#include <isc/string.h> +#include <isc/xml.h> + +#include <dns/cache.h> +#include <dns/callbacks.h> +#include <dns/db.h> +#include <dns/master.h> +#include <dns/masterdump.h> +#include <dns/name.h> +#include <dns/rdata.h> +#include <dns/rdatalist.h> +#include <dns/rdataset.h> + +#include "dnstest.h" + +/* + * Helper functions + */ + +#define BUFLEN 255 +#define BIGBUFLEN (70 * 1024) +#define TEST_ORIGIN "test" + +static dns_masterrawheader_t header; +static bool headerset; + +dns_name_t dns_origin; +char origin[sizeof(TEST_ORIGIN)]; +unsigned char name_buf[BUFLEN]; +dns_rdatacallbacks_t callbacks; +char *include_file = NULL; + +static isc_result_t +add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset); + +static void +rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *header); + +static isc_result_t +add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) { + char buf[BIGBUFLEN]; + isc_buffer_t target; + isc_result_t result; + + UNUSED(arg); + + isc_buffer_init(&target, buf, BIGBUFLEN); + result = dns_rdataset_totext(dataset, owner, false, false, + &target); + return(result); +} + +static void +rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *h) { + UNUSED(zone); + header = *h; + headerset = true; +} + +static isc_result_t +setup_master(void (*warn)(struct dns_rdatacallbacks *, const char *, ...), + void (*error)(struct dns_rdatacallbacks *, const char *, ...)) +{ + isc_result_t result; + int len; + isc_buffer_t source; + isc_buffer_t target; + + strlcpy(origin, TEST_ORIGIN, sizeof(origin)); + len = strlen(origin); + isc_buffer_init(&source, origin, len); + isc_buffer_add(&source, len); + isc_buffer_setactive(&source, len); + isc_buffer_init(&target, name_buf, BUFLEN); + dns_name_init(&dns_origin, NULL); + dns_master_initrawheader(&header); + + result = dns_name_fromtext(&dns_origin, &source, dns_rootname, + 0, &target); + if (result != ISC_R_SUCCESS) + return(result); + + dns_rdatacallbacks_init_stdio(&callbacks); + callbacks.add = add_callback; + callbacks.rawdata = rawdata_callback; + callbacks.zone = NULL; + if (warn != NULL) + callbacks.warn = warn; + if (error != NULL) + callbacks.error = error; + headerset = false; + return (result); +} + +static isc_result_t +test_master(const char *testfile, dns_masterformat_t format, + void (*warn)(struct dns_rdatacallbacks *, const char *, ...), + void (*error)(struct dns_rdatacallbacks *, const char *, ...)) +{ + isc_result_t result; + + result = setup_master(warn, error); + if (result != ISC_R_SUCCESS) + return(result); + + result = dns_master_loadfile2(testfile, &dns_origin, &dns_origin, + dns_rdataclass_in, true, + &callbacks, mctx, format); + return (result); +} + +static void +include_callback(const char *filename, void *arg) { + char **argp = (char **) arg; + *argp = isc_mem_strdup(mctx, filename); +} + +/* + * Individual unit tests + */ + +/* Successful load test */ +ATF_TC(load); +ATF_TC_HEAD(load, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a " + "valid master file and returns success"); +} +ATF_TC_BODY(load, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master1.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_test_end(); +} + + +/* Unepxected end of file test */ +ATF_TC(unexpected); +ATF_TC_HEAD(unexpected, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " + "DNS_R_UNEXPECTED when file ends " + "too soon"); +} +ATF_TC_BODY(unexpected, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master2.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_UNEXPECTEDEND); + + dns_test_end(); +} + + +/* No owner test */ +ATF_TC(noowner); +ATF_TC_HEAD(noowner, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() accepts broken " + "zones with no TTL for first record " + "if it is an SOA"); +} +ATF_TC_BODY(noowner, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master3.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, DNS_R_NOOWNER); + + dns_test_end(); +} + + +/* No TTL test */ +ATF_TC(nottl); +ATF_TC_HEAD(nottl, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " + "DNS_R_NOOWNER when no owner name " + "is specified"); +} + +ATF_TC_BODY(nottl, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master4.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_test_end(); +} + + +/* Bad class test */ +ATF_TC(badclass); +ATF_TC_HEAD(badclass, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " + "DNS_R_BADCLASS when record class " + "doesn't match zone class"); +} +ATF_TC_BODY(badclass, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master5.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, DNS_R_BADCLASS); + + dns_test_end(); +} + +/* Too big rdata test */ +ATF_TC(toobig); +ATF_TC_HEAD(toobig, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " + "ISC_R_NOSPACE when record is too big"); +} +ATF_TC_BODY(toobig, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master15.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_NOSPACE); + + dns_test_end(); +} + +/* Maximum rdata test */ +ATF_TC(maxrdata); +ATF_TC_HEAD(maxrdata, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " + "ISC_R_SUCCESS when record is maximum " + "size"); +} +ATF_TC_BODY(maxrdata, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master16.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_test_end(); +} + +/* DNSKEY test */ +ATF_TC(dnskey); +ATF_TC_HEAD(dnskey, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " + "DNSKEY with key material"); +} +ATF_TC_BODY(dnskey, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master6.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_test_end(); +} + + +/* DNSKEY with no key material test */ +ATF_TC(dnsnokey); +ATF_TC_HEAD(dnsnokey, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " + "DNSKEY with no key material"); +} +ATF_TC_BODY(dnsnokey, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master7.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_test_end(); +} + +/* Include test */ +ATF_TC(include); +ATF_TC_HEAD(include, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " + "$INCLUDE"); +} +ATF_TC_BODY(include, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master8.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, DNS_R_SEENINCLUDE); + + dns_test_end(); +} + +/* Include file list test */ +ATF_TC(master_includelist); +ATF_TC_HEAD(master_includelist, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile4() returns " + "names of included file"); +} +ATF_TC_BODY(master_includelist, tc) { + isc_result_t result; + char *filename = NULL; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = setup_master(NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_master_loadfile4("testdata/master/master8.data", + &dns_origin, &dns_origin, + dns_rdataclass_in, 0, true, + &callbacks, include_callback, + &filename, mctx, dns_masterformat_text); + ATF_CHECK_EQ(result, DNS_R_SEENINCLUDE); + ATF_CHECK(filename != NULL); + if (filename != NULL) { + ATF_CHECK_STREQ(filename, "testdata/master/master7.data"); + isc_mem_free(mctx, filename); + } + + dns_test_end(); +} + +/* Include failure test */ +ATF_TC(includefail); +ATF_TC_HEAD(includefail, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " + "$INCLUDE failures"); +} +ATF_TC_BODY(includefail, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master9.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, DNS_R_BADCLASS); + + dns_test_end(); +} + + +/* Non-empty blank lines test */ +ATF_TC(blanklines); +ATF_TC_HEAD(blanklines, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() handles " + "non-empty blank lines"); +} +ATF_TC_BODY(blanklines, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master10.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_test_end(); +} + +/* SOA leading zeroes test */ +ATF_TC(leadingzero); +ATF_TC_HEAD(leadingzero, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() allows " + "leading zeroes in SOA"); +} +ATF_TC_BODY(leadingzero, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("testdata/master/master11.data", + dns_masterformat_text, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_test_end(); +} + +ATF_TC(totext); +ATF_TC_HEAD(totext, tc) { + atf_tc_set_md_var(tc, "descr", "masterfile totext tests"); +} +ATF_TC_BODY(totext, tc) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + isc_buffer_t target; + unsigned char buf[BIGBUFLEN]; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* First, test with an empty rdataset */ + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = dns_rdataclass_in; + rdatalist.type = dns_rdatatype_none; + rdatalist.covers = dns_rdatatype_none; + + dns_rdataset_init(&rdataset); + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + isc_buffer_init(&target, buf, BIGBUFLEN); + result = dns_master_rdatasettotext(dns_rootname, + &rdataset, &dns_master_style_debug, + &target); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(isc_buffer_usedlength(&target), 0); + + /* + * XXX: We will also need to add tests for dumping various + * rdata types, classes, etc, and comparing the results against + * known-good output. + */ + + dns_test_end(); +} + +/* Raw load */ +ATF_TC(loadraw); +ATF_TC_HEAD(loadraw, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a " + "valid raw file and returns success"); +} +ATF_TC_BODY(loadraw, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Raw format version 0 */ + result = test_master("testdata/master/master12.data", + dns_masterformat_raw, NULL, NULL); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK_EQ(header.flags, 0); + + /* Raw format version 1, no source serial */ + result = test_master("testdata/master/master13.data", + dns_masterformat_raw, NULL, NULL); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK_EQ(header.flags, 0); + + /* Raw format version 1, source serial == 2011120101 */ + result = test_master("testdata/master/master14.data", + dns_masterformat_raw, NULL, NULL); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK((header.flags & DNS_MASTERRAW_SOURCESERIALSET) != 0); + ATF_CHECK_EQ(header.sourceserial, 2011120101); + + dns_test_end(); +} + +/* Raw dump*/ +ATF_TC(dumpraw); +ATF_TC_HEAD(dumpraw, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_dump*() functions " + "dump valid raw files"); +} +ATF_TC_BODY(dumpraw, tc) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbversion_t *version = NULL; + char myorigin[sizeof(TEST_ORIGIN)]; + dns_name_t dnsorigin; + isc_buffer_t source, target; + unsigned char namebuf[BUFLEN]; + int len; + + UNUSED(tc); + + strlcpy(myorigin, TEST_ORIGIN, sizeof(myorigin)); + len = strlen(myorigin); + isc_buffer_init(&source, myorigin, len); + isc_buffer_add(&source, len); + isc_buffer_setactive(&source, len); + isc_buffer_init(&target, namebuf, BUFLEN); + dns_name_init(&dnsorigin, NULL); + result = dns_name_fromtext(&dnsorigin, &source, dns_rootname, + 0, &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_create(mctx, "rbt", &dnsorigin, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_load(db, "testdata/master/master1.data"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_db_currentversion(db, &version); + + result = dns_master_dump2(mctx, db, version, + &dns_master_style_default, "test.dump", + dns_masterformat_raw); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("test.dump", dns_masterformat_raw, NULL, NULL); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK_EQ(header.flags, 0); + + dns_master_initrawheader(&header); + header.sourceserial = 12345; + header.flags |= DNS_MASTERRAW_SOURCESERIALSET; + + unlink("test.dump"); + result = dns_master_dump3(mctx, db, version, + &dns_master_style_default, "test.dump", + dns_masterformat_raw, &header); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("test.dump", dns_masterformat_raw, NULL, NULL); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK((header.flags & DNS_MASTERRAW_SOURCESERIALSET) != 0); + ATF_CHECK_EQ(header.sourceserial, 12345); + + unlink("test.dump"); + dns_db_closeversion(db, &version, false); + dns_db_detach(&db); + dns_test_end(); +} + +static const char *warn_expect_value; +static bool warn_expect_result; + +static void +warn_expect(struct dns_rdatacallbacks *mycallbacks, const char *fmt, ...) { + char buf[4096]; + va_list ap; + + UNUSED(mycallbacks); + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (warn_expect_value != NULL && strstr(buf, warn_expect_value) != NULL) + warn_expect_result = true; +} + +/* Origin change test */ +ATF_TC(neworigin); +ATF_TC_HEAD(neworigin, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() rejects " + "zones with inherited name following " + "$ORIGIN"); +} +ATF_TC_BODY(neworigin, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + warn_expect_value = "record with inherited owner"; + warn_expect_result = false; + result = test_master("testdata/master/master17.data", + dns_masterformat_text, warn_expect, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_MSG(warn_expect_result, "'%s' warning not emitted", + warn_expect_value); + + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, load); + ATF_TP_ADD_TC(tp, unexpected); + ATF_TP_ADD_TC(tp, noowner); + ATF_TP_ADD_TC(tp, nottl); + ATF_TP_ADD_TC(tp, badclass); + ATF_TP_ADD_TC(tp, dnskey); + ATF_TP_ADD_TC(tp, dnsnokey); + ATF_TP_ADD_TC(tp, include); + ATF_TP_ADD_TC(tp, master_includelist); + ATF_TP_ADD_TC(tp, includefail); + ATF_TP_ADD_TC(tp, blanklines); + ATF_TP_ADD_TC(tp, leadingzero); + ATF_TP_ADD_TC(tp, totext); + ATF_TP_ADD_TC(tp, loadraw); + ATF_TP_ADD_TC(tp, dumpraw); + ATF_TP_ADD_TC(tp, toobig); + ATF_TP_ADD_TC(tp, maxrdata); + ATF_TP_ADD_TC(tp, neworigin); + + return (atf_no_error()); +} diff --git a/lib/dns/tests/mkraw.pl b/lib/dns/tests/mkraw.pl new file mode 100644 index 0000000..9791adc --- /dev/null +++ b/lib/dns/tests/mkraw.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl -w +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# Convert a hexdump to binary format. +# +# To convert binary data to the input format for this command, +# use the following: +# +# perl -e 'while (read(STDIN, my $byte, 1)) { +# print unpack("H2", $byte); +# } +# print "\n";' < file > file.in + +use strict; +chomp(my $line = <STDIN>); +print pack("H*", $line); diff --git a/lib/dns/tests/name_test.c b/lib/dns/tests/name_test.c new file mode 100644 index 0000000..1953b41 --- /dev/null +++ b/lib/dns/tests/name_test.c @@ -0,0 +1,772 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <inttypes.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <atf-c.h> + +#include <isc/buffer.h> +#include <isc/commandline.h> +#include <isc/mem.h> +#include <isc/os.h> +#include <isc/print.h> +#include <isc/thread.h> +#include <isc/util.h> + +#include <dns/compress.h> +#include <dns/name.h> +#include <dns/fixedname.h> + +#include "dnstest.h" + +/* + * Individual unit tests + */ + +ATF_TC(fullcompare); +ATF_TC_HEAD(fullcompare, tc) { + atf_tc_set_md_var(tc, "descr", "dns_name_fullcompare test"); +} +ATF_TC_BODY(fullcompare, tc) { + dns_fixedname_t fixed1; + dns_fixedname_t fixed2; + dns_name_t *name1; + dns_name_t *name2; + dns_namereln_t relation; + int i; + isc_result_t result; + struct { + const char *name1; + const char *name2; + dns_namereln_t relation; + int order; + unsigned int nlabels; + } data[] = { + /* relative */ + { "", "", dns_namereln_equal, 0, 0 }, + { "foo", "", dns_namereln_subdomain, 1, 0 }, + { "", "foo", dns_namereln_contains, -1, 0 }, + { "foo", "bar", dns_namereln_none, 4, 0 }, + { "bar", "foo", dns_namereln_none, -4, 0 }, + { "bar.foo", "foo", dns_namereln_subdomain, 1, 1 }, + { "foo", "bar.foo", dns_namereln_contains, -1, 1 }, + { "baz.bar.foo", "bar.foo", dns_namereln_subdomain, 1, 2 }, + { "bar.foo", "baz.bar.foo", dns_namereln_contains, -1, 2 }, + { "foo.example", "bar.example", dns_namereln_commonancestor, + 4, 1 }, + + /* absolute */ + { ".", ".", dns_namereln_equal, 0, 1 }, + { "foo.", "bar.", dns_namereln_commonancestor, 4, 1 }, + { "bar.", "foo.", dns_namereln_commonancestor, -4, 1 }, + { "foo.example.", "bar.example.", dns_namereln_commonancestor, + 4, 2 }, + { "bar.foo.", "foo.", dns_namereln_subdomain, 1, 2 }, + { "foo.", "bar.foo.", dns_namereln_contains, -1, 2 }, + { "baz.bar.foo.", "bar.foo.", dns_namereln_subdomain, 1, 3 }, + { "bar.foo.", "baz.bar.foo.", dns_namereln_contains, -1, 3 }, + { NULL, NULL, dns_namereln_none, 0, 0 } + }; + + UNUSED(tc); + + name1 = dns_fixedname_initname(&fixed1); + name2 = dns_fixedname_initname(&fixed2); + for (i = 0; data[i].name1 != NULL; i++) { + int order = 3000; + unsigned int nlabels = 3000; + + if (data[i].name1[0] == 0) { + dns_fixedname_init(&fixed1); + } else { + result = dns_name_fromstring2(name1, data[i].name1, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + if (data[i].name2[0] == 0) { + dns_fixedname_init(&fixed2); + } else { + result = dns_name_fromstring2(name2, data[i].name2, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + relation = dns_name_fullcompare(name1, name1, &order, &nlabels); + ATF_REQUIRE_EQ(relation, dns_namereln_equal); + ATF_REQUIRE_EQ(order, 0); + ATF_REQUIRE_EQ(nlabels, name1->labels); + + /* Some random initializer */ + order = 3001; + nlabels = 3001; + + relation = dns_name_fullcompare(name1, name2, &order, &nlabels); + ATF_REQUIRE_EQ(relation, data[i].relation); + ATF_REQUIRE_EQ(order, data[i].order); + ATF_REQUIRE_EQ(nlabels, data[i].nlabels); + } +} + +static void +compress_test(dns_name_t *name1, dns_name_t *name2, dns_name_t *name3, + unsigned char *expected, unsigned int length, + dns_compress_t *cctx, dns_decompress_t *dctx) +{ + isc_buffer_t source; + isc_buffer_t target; + dns_name_t name; + unsigned char buf1[1024]; + unsigned char buf2[1024]; + + isc_buffer_init(&source, buf1, sizeof(buf1)); + isc_buffer_init(&target, buf2, sizeof(buf2)); + + ATF_REQUIRE_EQ(dns_name_towire(name1, cctx, &source), ISC_R_SUCCESS); + + ATF_CHECK_EQ(dns_name_towire(name2, cctx, &source), ISC_R_SUCCESS); + ATF_CHECK_EQ(dns_name_towire(name2, cctx, &source), ISC_R_SUCCESS); + ATF_CHECK_EQ(dns_name_towire(name3, cctx, &source), ISC_R_SUCCESS); + + isc_buffer_setactive(&source, source.used); + + dns_name_init(&name, NULL); + RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, false, + &target) == ISC_R_SUCCESS); + RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, false, + &target) == ISC_R_SUCCESS); + RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, false, + &target) == ISC_R_SUCCESS); + RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, false, + &target) == ISC_R_SUCCESS); + dns_decompress_invalidate(dctx); + + ATF_CHECK_EQ(target.used, length); + ATF_CHECK(memcmp(target.base, expected, target.used) == 0); +} + +ATF_TC(compression); +ATF_TC_HEAD(compression, tc) { + atf_tc_set_md_var(tc, "descr", "name compression test"); +} +ATF_TC_BODY(compression, tc) { + unsigned int allowed; + dns_compress_t cctx; + dns_decompress_t dctx; + dns_name_t name1; + dns_name_t name2; + dns_name_t name3; + isc_region_t r; + unsigned char plain1[] = "\003yyy\003foo"; + unsigned char plain2[] = "\003bar\003yyy\003foo"; + unsigned char plain3[] = "\003xxx\003bar\003foo"; + unsigned char plain[] = "\003yyy\003foo\0\003bar\003yyy\003foo\0\003" + "bar\003yyy\003foo\0\003xxx\003bar\003foo"; + + ATF_REQUIRE_EQ(dns_test_begin(NULL, false), ISC_R_SUCCESS);; + + dns_name_init(&name1, NULL); + r.base = plain1; + r.length = sizeof(plain1); + dns_name_fromregion(&name1, &r); + + dns_name_init(&name2, NULL); + r.base = plain2; + r.length = sizeof(plain2); + dns_name_fromregion(&name2, &r); + + dns_name_init(&name3, NULL); + r.base = plain3; + r.length = sizeof(plain3); + dns_name_fromregion(&name3, &r); + + /* Test 1: NONE */ + allowed = DNS_COMPRESS_NONE; + ATF_REQUIRE_EQ(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), + &cctx, &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test2: GLOBAL14 */ + allowed = DNS_COMPRESS_GLOBAL14; + ATF_REQUIRE_EQ(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), + &cctx, &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test3: ALL */ + allowed = DNS_COMPRESS_ALL; + ATF_REQUIRE_EQ(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), + &cctx, &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test4: NONE disabled */ + allowed = DNS_COMPRESS_NONE; + ATF_REQUIRE_EQ(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_compress_disable(&cctx); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), + &cctx, &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test5: GLOBAL14 disabled */ + allowed = DNS_COMPRESS_GLOBAL14; + ATF_REQUIRE_EQ(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_compress_disable(&cctx); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), + &cctx, &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test6: ALL disabled */ + allowed = DNS_COMPRESS_ALL; + ATF_REQUIRE_EQ(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_compress_disable(&cctx); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), + &cctx, &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + dns_test_end(); +} + +ATF_TC(istat); +ATF_TC_HEAD(istat, tc) { + atf_tc_set_md_var(tc, "descr", "is trust-anchor-telemetry test"); +} +ATF_TC_BODY(istat, tc) { + dns_fixedname_t fixed; + dns_name_t *name; + isc_result_t result; + size_t i; + struct { + const char *name; + bool istat; + } data[] = { + { ".", false }, + { "_ta-", false }, + { "_ta-1234", true }, + { "_TA-1234", true }, + { "+TA-1234", false }, + { "_fa-1234", false }, + { "_td-1234", false }, + { "_ta_1234", false }, + { "_ta-g234", false }, + { "_ta-1h34", false }, + { "_ta-12i4", false }, + { "_ta-123j", false }, + { "_ta-1234-abcf", true }, + { "_ta-1234-abcf-ED89", true }, + { "_ta-12345-abcf-ED89", false }, + { "_ta-.example", false }, + { "_ta-1234.example", true }, + { "_ta-1234-abcf.example", true }, + { "_ta-1234-abcf-ED89.example", true }, + { "_ta-12345-abcf-ED89.example", false }, + { "_ta-1234-abcfe-ED89.example", false }, + { "_ta-1234-abcf-EcD89.example", false } + }; + + name = dns_fixedname_initname(&fixed); + + for (i = 0; i < sizeof(data)/sizeof(data[0]); i++) { + result = dns_name_fromstring(name, data[i].name, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ_MSG(dns_name_istat(name), data[i].istat, + "testing %s - expected %u", data[i].name, data[i].istat); + } +} + +ATF_TC(init); +ATF_TC_HEAD(init, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_init"); +} +ATF_TC_BODY(init, tc) { + dns_name_t name; + unsigned char offsets[1]; + + dns_name_init(&name, offsets); + + ATF_CHECK_EQ(name.ndata, NULL); + ATF_CHECK_EQ(name.length, 0); + ATF_CHECK_EQ(name.labels, 0); + ATF_CHECK_EQ(name.attributes, 0); + ATF_CHECK_EQ(name.offsets, offsets); + ATF_CHECK_EQ(name.buffer, NULL); +} + +ATF_TC(invalidate); +ATF_TC_HEAD(invalidate, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_invalidate"); +} +ATF_TC_BODY(invalidate, tc) { + dns_name_t name; + unsigned char offsets[1]; + + dns_name_init(&name, offsets); + dns_name_invalidate(&name); + + ATF_CHECK_EQ(name.ndata, NULL); + ATF_CHECK_EQ(name.length, 0); + ATF_CHECK_EQ(name.labels, 0); + ATF_CHECK_EQ(name.attributes, 0); + ATF_CHECK_EQ(name.offsets, NULL); + ATF_CHECK_EQ(name.buffer, NULL); +} + +ATF_TC(buffer); +ATF_TC_HEAD(buffer, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_setbuffer/hasbuffer"); +} +ATF_TC_BODY(buffer, tc) { + dns_name_t name; + unsigned char buf[BUFSIZ]; + isc_buffer_t b; + + isc_buffer_init(&b, buf, BUFSIZ); + dns_name_init(&name, NULL); + dns_name_setbuffer(&name, &b); + ATF_CHECK_EQ(name.buffer, &b); + ATF_CHECK(dns_name_hasbuffer(&name)); +} + +ATF_TC(isabsolute); +ATF_TC_HEAD(isabsolute, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_isabsolute"); +} +ATF_TC_BODY(isabsolute, tc) { + struct { + const char *namestr; + bool expect; + } testcases[] = { + { "x", false }, + { "a.b.c.d.", true }, + { "x.z", false} + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) { + isc_result_t result; + dns_name_t name; + unsigned char data[BUFSIZ]; + isc_buffer_t b, nb; + size_t len; + + len = strlen(testcases[i].namestr); + isc_buffer_constinit(&b, testcases[i].namestr, len); + isc_buffer_add(&b, len); + + dns_name_init(&name, NULL); + isc_buffer_init(&nb, data, BUFSIZ); + dns_name_setbuffer(&name, &nb); + result = dns_name_fromtext(&name, &b, NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_CHECK_EQ(dns_name_isabsolute(&name), testcases[i].expect); + } +} + +ATF_TC(hash); +ATF_TC_HEAD(hash, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_hash"); +} +ATF_TC_BODY(hash, tc) { + struct { + const char *name1; + const char *name2; + bool expect; + bool expecti; + } testcases[] = { + { "a.b.c.d", "A.B.C.D", true, false }, + { "a.b.c.d.", "A.B.C.D.", true, false }, + { "a.b.c.d", "a.b.c.d", true, true }, + { "A.B.C.D.", "A.B.C.D.", true, false }, + { "x.y.z.w", "a.b.c.d", false, false }, + { "x.y.z.w.", "a.b.c.d.", false, false }, + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) { + isc_result_t result; + dns_fixedname_t f1, f2; + dns_name_t *n1, *n2; + unsigned int h1, h2; + + n1 = dns_fixedname_initname(&f1); + n2 = dns_fixedname_initname(&f2); + + result = dns_name_fromstring2(n1, testcases[i].name1, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_name_fromstring2(n2, testcases[i].name2, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Check case-insensitive hashing first */ + h1 = dns_name_hash(n1, false); + h2 = dns_name_hash(n2, false); + + printf("%s hashes to %u, %s to %u, case insensitive\n", + testcases[i].name1, h1, testcases[i].name2, h2); + + ATF_REQUIRE_EQ((h1 == h2), testcases[i].expect); + + /* Now case-sensitive */ + h1 = dns_name_hash(n1, false); + h2 = dns_name_hash(n2, false); + + printf("%s hashes to %u, %s to %u, case sensitive\n", + testcases[i].name1, h1, testcases[i].name2, h2); + + ATF_REQUIRE_EQ((h1 == h2), testcases[i].expect); + } +} + +ATF_TC(issubdomain); +ATF_TC_HEAD(issubdomain, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_issubdomain"); +} +ATF_TC_BODY(issubdomain, tc) { + struct { + const char *name1; + const char *name2; + bool expect; + } testcases[] = { + { "c.d", "a.b.c.d", false }, + { "c.d.", "a.b.c.d.", false }, + { "b.c.d", "c.d", true }, + { "a.b.c.d.", "c.d.", true }, + { "a.b.c", "a.b.c", true }, + { "a.b.c.", "a.b.c.", true }, + { "x.y.z", "a.b.c", false} + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) { + isc_result_t result; + dns_fixedname_t f1, f2; + dns_name_t *n1, *n2; + + n1 = dns_fixedname_initname(&f1); + n2 = dns_fixedname_initname(&f2); + + result = dns_name_fromstring2(n1, testcases[i].name1, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_name_fromstring2(n2, testcases[i].name2, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + printf("check: %s %s a subdomain of %s\n", + testcases[i].name1, + testcases[i].expect ? "is" : "is not", + testcases[i].name2); + + ATF_CHECK_EQ(dns_name_issubdomain(n1, n2), + testcases[i].expect); + } +} + +ATF_TC(countlabels); +ATF_TC_HEAD(countlabels, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_countlabels"); +} +ATF_TC_BODY(countlabels, tc) { + struct { + const char *namestr; + unsigned int expect; + } testcases[] = { + { "c.d", 2 }, + { "c.d.", 3 }, + { "a.b.c.d.", 5 }, + { "a.b.c.d", 4 }, + { "a.b.c", 3 }, + { ".", 1 }, + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) { + isc_result_t result; + dns_fixedname_t fname; + dns_name_t *name; + + name = dns_fixedname_initname(&fname); + + result = dns_name_fromstring2(name, testcases[i].namestr, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + printf("%s: expect %u labels\n", + testcases[i].namestr, testcases[i].expect); + + ATF_REQUIRE_EQ(dns_name_countlabels(name), + testcases[i].expect); + } +} + +ATF_TC(getlabel); +ATF_TC_HEAD(getlabel, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_getlabel"); +} +ATF_TC_BODY(getlabel, tc) { + struct { + const char *name1; + unsigned int pos1; + const char *name2; + unsigned int pos2; + } testcases[] = { + { "c.d", 1, "a.b.c.d", 3 }, + { "a.b.c.d", 3, "c.d", 1 }, + { "a.b.c.", 3, "A.B.C.", 3 }, + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) { + isc_result_t result; + dns_fixedname_t f1, f2; + dns_name_t *n1, *n2; + dns_label_t l1, l2; + unsigned char *p1, *p2; + unsigned int j; + + n1 = dns_fixedname_initname(&f1); + n2 = dns_fixedname_initname(&f2); + + result = dns_name_fromstring2(n1, testcases[i].name1, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_name_fromstring2(n2, testcases[i].name2, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_name_getlabel(n1, testcases[i].pos1, &l1); + dns_name_getlabel(n2, testcases[i].pos2, &l2); + ATF_CHECK_EQ(l1.length, l2.length); + + p1 = l1.base; + p2 = l2.base; + for (j = 0; j < l1.length; j++) { + ATF_REQUIRE_EQ(*p1++, *p2++); + } + } +} + +ATF_TC(getlabelsequence); +ATF_TC_HEAD(getlabelsequence, tc) { + atf_tc_set_md_var(tc, "descr", "dns_nane_getlabelsequence"); +} +ATF_TC_BODY(getlabelsequence, tc) { + struct { + const char *name1; + unsigned int pos1; + const char *name2; + unsigned int pos2; + unsigned int range; + } testcases[] = { + { "c.d", 1, "a.b.c.d", 3, 1 }, + { "a.b.c.d.e", 2, "c.d", 0, 2 }, + { "a.b.c", 0, "a.b.c", 0, 3 }, + + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) { + isc_result_t result; + dns_name_t t1, t2; + dns_fixedname_t f1, f2; + dns_name_t *n1, *n2; + + /* target names */ + dns_name_init(&t1, NULL); + dns_name_init(&t2, NULL); + + /* source names */ + n1 = dns_fixedname_initname(&f1); + n2 = dns_fixedname_initname(&f2); + + result = dns_name_fromstring2(n1, testcases[i].name1, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_name_fromstring2(n2, testcases[i].name2, + NULL, 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_name_getlabelsequence(n1, testcases[i].pos1, + testcases[i].range, &t1); + dns_name_getlabelsequence(n2, testcases[i].pos2, + testcases[i].range, &t2); + + ATF_REQUIRE(dns_name_equal(&t1, &t2)); + } +} + +#ifdef ISC_PLATFORM_USETHREADS +#ifdef DNS_BENCHMARK_TESTS + +/* + * XXXMUKS: Don't delete this code. It is useful in benchmarking the + * name parser, but we don't require it as part of the unit test runs. + */ + +ATF_TC(benchmark); +ATF_TC_HEAD(benchmark, tc) { + atf_tc_set_md_var(tc, "descr", + "Benchmark dns_name_fromwire() implementation"); +} + +static void * +fromwire_thread(void *arg) { + unsigned int maxval = 32000000; + uint8_t data[] = { + 3, 'w', 'w', 'w', + 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 7, 'i', 'n', 'v', 'a', 'l', 'i', 'd', + 0 + }; + unsigned char output_data[DNS_NAME_MAXWIRE]; + isc_buffer_t source, target; + unsigned int i; + dns_decompress_t dctx; + + UNUSED(arg); + + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, DNS_COMPRESS_NONE); + + isc_buffer_init(&source, data, sizeof(data)); + isc_buffer_add(&source, sizeof(data)); + isc_buffer_init(&target, output_data, sizeof(output_data)); + + /* Parse 32 million names in each thread */ + for (i = 0; i < maxval; i++) { + dns_name_t name; + + isc_buffer_clear(&source); + isc_buffer_clear(&target); + isc_buffer_add(&source, sizeof(data)); + isc_buffer_setactive(&source, sizeof(data)); + + dns_name_init(&name, NULL); + (void) dns_name_fromwire(&name, &source, &dctx, 0, &target); + } + + return (NULL); +} + +ATF_TC_BODY(benchmark, tc) { + isc_result_t result; + unsigned int i; + isc_time_t ts1, ts2; + double t; + unsigned int nthreads; + isc_thread_t threads[32]; + + UNUSED(tc); + + debug_mem_record = false; + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_time_now(&ts1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + nthreads = ISC_MIN(isc_os_ncpus(), 32); + nthreads = ISC_MAX(nthreads, 1); + for (i = 0; i < nthreads; i++) { + result = isc_thread_create(fromwire_thread, NULL, &threads[i]); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + + for (i = 0; i < nthreads; i++) { + result = isc_thread_join(threads[i], NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + + result = isc_time_now(&ts2); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + t = isc_time_microdiff(&ts2, &ts1); + + printf("%u dns_name_fromwire() calls, %f seconds, %f calls/second\n", + nthreads * 32000000, t / 1000000.0, + (nthreads * 32000000) / (t / 1000000.0)); + + dns_test_end(); +} + +#endif /* DNS_BENCHMARK_TESTS */ +#endif /* ISC_PLATFORM_USETHREADS */ + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, fullcompare); + ATF_TP_ADD_TC(tp, compression); + ATF_TP_ADD_TC(tp, istat); + ATF_TP_ADD_TC(tp, init); + ATF_TP_ADD_TC(tp, invalidate); + ATF_TP_ADD_TC(tp, buffer); + ATF_TP_ADD_TC(tp, isabsolute); + ATF_TP_ADD_TC(tp, hash); + ATF_TP_ADD_TC(tp, issubdomain); + ATF_TP_ADD_TC(tp, countlabels); + ATF_TP_ADD_TC(tp, getlabel); + ATF_TP_ADD_TC(tp, getlabelsequence); +#ifdef ISC_PLATFORM_USETHREADS +#ifdef DNS_BENCHMARK_TESTS + ATF_TP_ADD_TC(tp, benchmark); +#endif /* DNS_BENCHMARK_TESTS */ +#endif /* ISC_PLATFORM_USETHREADS */ + + return (atf_no_error()); +} diff --git a/lib/dns/tests/nsec3_test.c b/lib/dns/tests/nsec3_test.c new file mode 100644 index 0000000..8a53344 --- /dev/null +++ b/lib/dns/tests/nsec3_test.c @@ -0,0 +1,207 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> + +#include <dns/db.h> +#include <dns/nsec3.h> + +#include "dnstest.h" + +#if defined(OPENSSL) || defined(PKCS11CRYPTO) +/* + * Helper functions + */ + +static void +iteration_test(const char *file, unsigned int expected) { + isc_result_t result; + dns_db_t *db = NULL; + unsigned int iterations; + + result = dns_test_loaddb(&db, dns_dbtype_zone, "test", file); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", file); + + result = dns_nsec3_maxiterations(db, NULL, mctx, &iterations); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", file); + + ATF_CHECK_EQ_MSG(iterations, expected, "%s", file); + + dns_db_detach(&db); +} + +/*% + * Structure containing parameters for nsec3param_salttotext_test(). + */ +typedef struct { + const char *nsec3param_text; /* NSEC3PARAM RDATA in text form */ + const char *expected_salt; /* string expected in target buffer */ +} nsec3param_salttotext_test_params_t; + +/*% + * Check whether dns_nsec3param_salttotext() handles supplied text form + * NSEC3PARAM RDATA correctly: test whether the result of calling the former is + * as expected and whether it properly checks available buffer space. + * + * Assumes supplied text form NSEC3PARAM RDATA is valid as testing handling of + * invalid NSEC3PARAM RDATA is out of scope of this unit test. + */ +static void +nsec3param_salttotext_test(const nsec3param_salttotext_test_params_t *params) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3param_t nsec3param; + unsigned char buf[1024]; + isc_result_t result; + char salt[64]; + size_t length; + + /* + * Prepare a dns_rdata_nsec3param_t structure for testing. + */ + result = dns_test_rdatafromstring(&rdata, dns_rdataclass_in, + dns_rdatatype_nsec3param, buf, + sizeof(buf), + params->nsec3param_text); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Check typical use. + */ + result = dns_nsec3param_salttotext(&nsec3param, salt, sizeof(salt)); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "\"%s\": expected success, got %s\n", + params->nsec3param_text, isc_result_totext(result)); + ATF_CHECK_EQ_MSG(strcmp(salt, params->expected_salt), 0, + "\"%s\": expected salt \"%s\", got \"%s\"", + params->nsec3param_text, params->expected_salt, salt); + + /* + * Ensure available space in the buffer is checked before the salt is + * printed to it and that the amount of space checked for includes the + * terminating NULL byte. + */ + length = strlen(params->expected_salt); + ATF_REQUIRE(length < sizeof(salt) - 1); /* prevent buffer overwrite */ + ATF_REQUIRE(length > 0U); /* prevent length underflow */ + + result = dns_nsec3param_salttotext(&nsec3param, salt, length - 1); + ATF_CHECK_EQ_MSG(result, ISC_R_NOSPACE, + "\"%s\": expected a %lu-byte target buffer to be " + "rejected, got %s\n", + params->nsec3param_text, (unsigned long)(length - 1), + isc_result_totext(result)); + result = dns_nsec3param_salttotext(&nsec3param, salt, length); + ATF_CHECK_EQ_MSG(result, ISC_R_NOSPACE, + "\"%s\": expected a %lu-byte target buffer to be " + "rejected, got %s\n", + params->nsec3param_text, (unsigned long)length, + isc_result_totext(result)); + result = dns_nsec3param_salttotext(&nsec3param, salt, length + 1); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "\"%s\": expected a %lu-byte target buffer to be " + "accepted, got %s\n", + params->nsec3param_text, (unsigned long)(length + 1), + isc_result_totext(result)); +} + +/* + * Individual unit tests + */ + +ATF_TC(max_iterations); +ATF_TC_HEAD(max_iterations, tc) { + atf_tc_set_md_var(tc, "descr", "check that appropriate max iterations " + " is returned for different key size mixes"); +} +ATF_TC_BODY(max_iterations, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + iteration_test("testdata/nsec3/1024.db", 150); + iteration_test("testdata/nsec3/2048.db", 500); + iteration_test("testdata/nsec3/4096.db", 2500); + iteration_test("testdata/nsec3/min-1024.db", 150); + iteration_test("testdata/nsec3/min-2048.db", 500); + + dns_test_end(); +} + +ATF_TC(nsec3param_salttotext); +ATF_TC_HEAD(nsec3param_salttotext, tc) { + atf_tc_set_md_var(tc, "descr", "check dns_nsec3param_salttotext()"); +} +ATF_TC_BODY(nsec3param_salttotext, tc) { + isc_result_t result; + size_t i; + + const nsec3param_salttotext_test_params_t tests[] = { + /* + * Tests with non-empty salts. + */ + { "0 0 10 0123456789abcdef", "0123456789ABCDEF" }, + { "0 1 11 0123456789abcdef", "0123456789ABCDEF" }, + { "1 0 12 42", "42" }, + { "1 1 13 42", "42" }, + /* + * Test with empty salt. + */ + { "0 0 0 -", "-" }, + }; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + nsec3param_salttotext_test(&tests[i]); + } + + dns_test_end(); +} +#else +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping nsec3 test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("DNSSEC not available"); +} +#endif + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { +#if defined(OPENSSL) || defined(PKCS11CRYPTO) + ATF_TP_ADD_TC(tp, max_iterations); + ATF_TP_ADD_TC(tp, nsec3param_salttotext); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + + return (atf_no_error()); +} + diff --git a/lib/dns/tests/peer_test.c b/lib/dns/tests/peer_test.c new file mode 100644 index 0000000..1cff105 --- /dev/null +++ b/lib/dns/tests/peer_test.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> + +#include <dns/peer.h> + +#include "dnstest.h" + +/* + * Individual unit tests + */ +ATF_TC(dscp); +ATF_TC_HEAD(dscp, tc) { + atf_tc_set_md_var(tc, "descr", + "Test DSCP set/get functions"); +} +ATF_TC_BODY(dscp, tc) { + isc_result_t result; + isc_netaddr_t netaddr; + struct in_addr ina; + dns_peer_t *peer = NULL; + isc_dscp_t dscp; + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Create peer structure for the loopback address. + */ + ina.s_addr = INADDR_LOOPBACK; + isc_netaddr_fromin(&netaddr, &ina); + result = dns_peer_new(mctx, &netaddr, &peer); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * All should be not set on creation. + * 'dscp' should remain unchanged. + */ + dscp = 100; + result = dns_peer_getquerydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_getnotifydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_gettransferdscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + /* + * Test that setting query dscp does not affect the other + * dscp values. 'dscp' should remain unchanged until + * dns_peer_getquerydscp is called. + */ + dscp = 100; + result = dns_peer_setquerydscp(peer, 1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_peer_getnotifydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_gettransferdscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_getquerydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 1); + + /* + * Test that setting notify dscp does not affect the other + * dscp values. 'dscp' should remain unchanged until + * dns_peer_getquerydscp is called then should change again + * on dns_peer_getnotifydscp. + */ + dscp = 100; + result = dns_peer_setnotifydscp(peer, 2); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_peer_gettransferdscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_getquerydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 1); + + result = dns_peer_getnotifydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 2); + + /* + * Test that setting notify dscp does not affect the other + * dscp values. Check that appropriate values are returned. + */ + dscp = 100; + result = dns_peer_settransferdscp(peer, 3); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_peer_getquerydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 1); + + result = dns_peer_getnotifydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 2); + + result = dns_peer_gettransferdscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 3); + + dns_peer_detach(&peer); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, dscp); + return (atf_no_error()); +} diff --git a/lib/dns/tests/private_test.c b/lib/dns/tests/private_test.c new file mode 100644 index 0000000..dcb859e --- /dev/null +++ b/lib/dns/tests/private_test.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <inttypes.h> +#include <stdbool.h> +#include <unistd.h> + +#include <isc/buffer.h> + +#include <dns/nsec3.h> +#include <dns/private.h> +#include <dns/rdataclass.h> +#include <dns/rdatatype.h> + +#include <dst/dst.h> + +#include "dnstest.h" + +static dns_rdatatype_t privatetype = 65534; + +typedef struct { + unsigned char alg; + dns_keytag_t keyid; + bool remove; + bool complete; +} signing_testcase_t; + +typedef struct { + unsigned char hash; + unsigned char flags; + unsigned int iterations; + unsigned long salt; + bool remove; + bool pending; + bool nonsec; +} nsec3_testcase_t; + +/* + * Helper functions + */ +static void +make_signing(signing_testcase_t *testcase, dns_rdata_t *private, + unsigned char *buf, size_t len) +{ + dns_rdata_init(private); + + buf[0] = testcase->alg; + buf[1] = (testcase->keyid & 0xff00) >> 8; + buf[2] = (testcase->keyid & 0xff); + buf[3] = testcase->remove; + buf[4] = testcase->complete; + private->data = buf; + private->length = len; + private->type = privatetype; + private->rdclass = dns_rdataclass_in; +} + +static void +make_nsec3(nsec3_testcase_t *testcase, dns_rdata_t *private, + unsigned char *pbuf) +{ + dns_rdata_nsec3param_t params; + dns_rdata_t nsec3param = DNS_RDATA_INIT; + unsigned char bufdata[BUFSIZ]; + isc_buffer_t buf; + uint32_t salt; + unsigned char *sp; + int slen = 4; + + /* for simplicity, we're using a maximum salt length of 4 */ + salt = htonl(testcase->salt); + sp = (unsigned char *) &salt; + while (*sp == '\0' && slen > 0) { + slen--; + sp++; + } + + params.common.rdclass = dns_rdataclass_in; + params.common.rdtype = dns_rdatatype_nsec3param; + params.hash = testcase->hash; + params.iterations = testcase->iterations; + params.salt = sp; + params.salt_length = slen; + + params.flags = testcase->flags; + if (testcase->remove) { + params.flags |= DNS_NSEC3FLAG_REMOVE; + if (testcase->nonsec) + params.flags |= DNS_NSEC3FLAG_NONSEC; + } else { + params.flags |= DNS_NSEC3FLAG_CREATE; + if (testcase->pending) + params.flags |= DNS_NSEC3FLAG_INITIAL; + } + + isc_buffer_init(&buf, bufdata, sizeof(bufdata)); + dns_rdata_fromstruct(&nsec3param, dns_rdataclass_in, + dns_rdatatype_nsec3param, ¶ms, &buf); + + dns_rdata_init(private); + + dns_nsec3param_toprivate(&nsec3param, private, privatetype, + pbuf, DNS_NSEC3PARAM_BUFFERSIZE + 1); +} + +/* + * Individual unit tests + */ +ATF_TC(private_signing_totext); +ATF_TC_HEAD(private_signing_totext, tc) { + atf_tc_set_md_var(tc, "descr", + "convert private signing records to text"); +} +ATF_TC_BODY(private_signing_totext, tc) { + isc_result_t result; + dns_rdata_t private; + int i; + + signing_testcase_t testcases[] = { + { DST_ALG_RSASHA512, 12345, 0, 0 }, + { DST_ALG_RSASHA256, 54321, 1, 0 }, + { DST_ALG_NSEC3RSASHA1, 22222, 0, 1 }, + { DST_ALG_RSASHA1, 33333, 1, 1 } + }; + const char *results[] = { + "Signing with key 12345/RSASHA512", + "Removing signatures for key 54321/RSASHA256", + "Done signing with key 22222/NSEC3RSASHA1", + "Done removing signatures for key 33333/RSASHA1" + }; + int ncases = 4; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (i = 0; i < ncases; i++) { + unsigned char data[5]; + char output[BUFSIZ]; + isc_buffer_t buf; + + isc_buffer_init(&buf, output, sizeof(output)); + + make_signing(&testcases[i], &private, data, sizeof(data)); + dns_private_totext(&private, &buf); + ATF_CHECK_STREQ(output, results[i]); + } + + dns_test_end(); +} + +ATF_TC(private_nsec3_totext); +ATF_TC_HEAD(private_nsec3_totext, tc) { + atf_tc_set_md_var(tc, "descr", "convert private chain records to text"); +} +ATF_TC_BODY(private_nsec3_totext, tc) { + isc_result_t result; + dns_rdata_t private; + int i; + + nsec3_testcase_t testcases[] = { + { 1, 0, 1, 0xbeef, 0, 0, 0 }, + { 1, 1, 10, 0xdadd, 0, 0, 0 }, + { 1, 0, 20, 0xbead, 0, 1, 0 }, + { 1, 0, 30, 0xdeaf, 1, 0, 0 }, + { 1, 0, 100, 0xfeedabee, 1, 0, 1 }, + }; + const char *results[] = { + "Creating NSEC3 chain 1 0 1 BEEF", + "Creating NSEC3 chain 1 1 10 DADD", + "Pending NSEC3 chain 1 0 20 BEAD", + "Removing NSEC3 chain 1 0 30 DEAF / creating NSEC chain", + "Removing NSEC3 chain 1 0 100 FEEDABEE" + }; + int ncases = 5; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (i = 0; i < ncases; i++) { + unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1]; + char output[BUFSIZ]; + isc_buffer_t buf; + + isc_buffer_init(&buf, output, sizeof(output)); + + make_nsec3(&testcases[i], &private, data); + dns_private_totext(&private, &buf); + ATF_CHECK_STREQ(output, results[i]); + } + + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, private_signing_totext); + ATF_TP_ADD_TC(tp, private_nsec3_totext); + return (atf_no_error()); +} diff --git a/lib/dns/tests/rbt_serialize_test.c b/lib/dns/tests/rbt_serialize_test.c new file mode 100644 index 0000000..07d4e56 --- /dev/null +++ b/lib/dns/tests/rbt_serialize_test.c @@ -0,0 +1,456 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* ! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <inttypes.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> + +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/random.h> +#include <isc/string.h> + +#include <dns/rbt.h> +#include <dns/fixedname.h> +#include <dns/result.h> +#include <dns/compress.h> +#include "dnstest.h" + +#include <isc/app.h> +#include <isc/buffer.h> +#include <isc/entropy.h> +#include <isc/file.h> +#include <isc/hash.h> +#include <isc/mem.h> +#include <isc/os.h> +#include <isc/string.h> +#include <isc/socket.h> +#include <isc/stdio.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/log.h> +#include <dns/name.h> +#include <dns/result.h> + +#include <dst/dst.h> + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +typedef struct data_holder { + int len; + const char *data; +} data_holder_t; + +typedef struct rbt_testdata { + const char *name; + size_t name_len; + data_holder_t data; +} rbt_testdata_t; + +#define DATA_ITEM(name) { (name), sizeof(name) - 1, { sizeof(name), (name) } } + +rbt_testdata_t testdata[] = { + DATA_ITEM("first.com."), + DATA_ITEM("one.net."), + DATA_ITEM("two.com."), + DATA_ITEM("three.org."), + DATA_ITEM("asdf.com."), + DATA_ITEM("ghjkl.com."), + DATA_ITEM("1.edu."), + DATA_ITEM("2.edu."), + DATA_ITEM("3.edu."), + DATA_ITEM("123.edu."), + DATA_ITEM("1236.com."), + DATA_ITEM("and_so_forth.com."), + DATA_ITEM("thisisalongname.com."), + DATA_ITEM("a.b."), + DATA_ITEM("test.net."), + DATA_ITEM("whoknows.org."), + DATA_ITEM("blargh.com."), + DATA_ITEM("www.joe.com."), + DATA_ITEM("test.com."), + DATA_ITEM("isc.org."), + DATA_ITEM("uiop.mil."), + DATA_ITEM("last.fm."), + { NULL, 0, { 0, NULL } } +}; + +static void +delete_data(void *data, void *arg) { + UNUSED(arg); + UNUSED(data); +} + +static isc_result_t +write_data(FILE *file, unsigned char *datap, void *arg, uint64_t *crc) { + isc_result_t result; + size_t ret = 0; + data_holder_t *data = (data_holder_t *)datap; + data_holder_t temp; + off_t where; + + UNUSED(arg); + + REQUIRE(file != NULL); + REQUIRE(crc != NULL); + REQUIRE(data != NULL); + REQUIRE((data->len == 0 && data->data == NULL) || + (data->len != 0 && data->data != NULL)); + + result = isc_stdio_tell(file, &where); + if (result != ISC_R_SUCCESS) + return (result); + + temp = *data; + temp.data = (data->len == 0 + ? NULL + : (char *)((uintptr_t)where + sizeof(data_holder_t))); + + isc_crc64_update(crc, (void *)&temp, sizeof(temp)); + ret = fwrite(&temp, sizeof(data_holder_t), 1, file); + if (ret != 1) + return (ISC_R_FAILURE); + if (data->len > 0) { + isc_crc64_update(crc, (const void *)data->data, data->len); + ret = fwrite(data->data, data->len, 1, file); + if (ret != 1) + return (ISC_R_FAILURE); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +fix_data(dns_rbtnode_t *p, void *base, size_t max, void *arg, + uint64_t *crc) +{ + data_holder_t *data = p->data; + size_t size; + + UNUSED(base); + UNUSED(max); + UNUSED(arg); + + REQUIRE(crc != NULL); + REQUIRE(p != NULL); + + + if (data == NULL) + printf("fixing data: data NULL\n"); + else + printf("fixing data: len %d, data %p\n", data->len, data->data); + + if (data == NULL || + (data->len == 0 && data->data != NULL) || + (data->len != 0 && data->data == NULL)) + return (ISC_R_INVALIDFILE); + + size = max - ((char *)p - (char *)base); + + if (data->len > (int) size || data->data > (const char *) max) { + printf("data invalid\n"); + return (ISC_R_INVALIDFILE); + } + + isc_crc64_update(crc, (void *)data, sizeof(*data)); + + data->data = (data->len == 0) + ? NULL + : (char *)data + sizeof(data_holder_t); + + if (data->len > 0) + isc_crc64_update(crc, (const void *)data->data, data->len); + + return (ISC_R_SUCCESS); +} + +/* + * Load test data into the RBT. + */ +static void +add_test_data(isc_mem_t *mymctx, dns_rbt_t *rbt) { + char buffer[1024]; + isc_buffer_t b; + isc_result_t result; + dns_fixedname_t fname; + dns_name_t *name; + dns_compress_t cctx; + rbt_testdata_t *testdatap = testdata; + + dns_compress_init(&cctx, -1, mymctx); + + while (testdatap->name != NULL && testdatap->data.data != NULL) { + memmove(buffer, testdatap->name, testdatap->name_len); + + isc_buffer_init(&b, buffer, testdatap->name_len); + isc_buffer_add(&b, testdatap->name_len); + name = dns_fixedname_initname(&fname); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + testdatap++; + continue; + } + + if (name != NULL) { + result = dns_rbt_addname(rbt, name, &testdatap->data); + ATF_CHECK_STREQ(dns_result_totext(result), "success"); + } + testdatap++; + } + + dns_compress_invalidate(&cctx); +} + +/* + * Walk the tree and ensure that all the test nodes are present. + */ +static void +check_test_data(dns_rbt_t *rbt) { + char buffer[1024]; + char *arg; + dns_fixedname_t fname; + dns_fixedname_t fixed; + dns_name_t *name; + isc_buffer_t b; + data_holder_t *data; + isc_result_t result; + dns_name_t *foundname; + rbt_testdata_t *testdatap = testdata; + + foundname = dns_fixedname_initname(&fixed); + + while (testdatap->name != NULL && testdatap->data.data != NULL) { + memmove(buffer, testdatap->name, testdatap->name_len + 1); + arg = buffer; + + isc_buffer_init(&b, arg, testdatap->name_len); + isc_buffer_add(&b, testdatap->name_len); + name = dns_fixedname_initname(&fname); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + testdatap++; + continue; + } + + data = NULL; + result = dns_rbt_findname(rbt, name, 0, foundname, + (void *) &data); + ATF_CHECK_STREQ(dns_result_totext(result), "success"); + + testdatap++; + } +} + +static void +data_printer(FILE *out, void *datap) +{ + data_holder_t *data = (data_holder_t *)datap; + + fprintf(out, "%d bytes, %s", data->len, data->data); +} + +ATF_TC(serialize); +ATF_TC_HEAD(serialize, tc) { + atf_tc_set_md_var(tc, "descr", "Test writing an rbt to file"); +} +ATF_TC_BODY(serialize, tc) { + dns_rbt_t *rbt = NULL; + isc_result_t result; + FILE *rbtfile = NULL; + dns_rbt_t *rbt_deserialized = NULL; + off_t offset; + int fd; + off_t filesize = 0; + char *base; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_STREQ(dns_result_totext(result), "success"); + result = dns_rbt_create(mctx, delete_data, NULL, &rbt); + ATF_CHECK_STREQ(dns_result_totext(result), "success"); + + add_test_data(mctx, rbt); + + dns_rbt_printtext(rbt, data_printer, stdout); + + /* + * Serialize the tree. + */ + printf("serialization begins.\n"); + rbtfile = fopen("./zone.bin", "w+b"); + ATF_REQUIRE(rbtfile != NULL); + result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL, + &offset); + ATF_REQUIRE(result == ISC_R_SUCCESS); + dns_rbt_destroy(&rbt); + + /* + * Deserialize the tree + */ + printf("deserialization begins.\n"); + + /* + * Map in the whole file in one go + */ + fd = open("zone.bin", O_RDWR); + isc_file_getsizefd(fd, &filesize); + base = mmap(NULL, filesize, + PROT_READ|PROT_WRITE, + MAP_FILE|MAP_PRIVATE, fd, 0); + ATF_REQUIRE(base != NULL && base != MAP_FAILED); + close(fd); + + result = dns_rbt_deserialize_tree(base, filesize, 0, mctx, + delete_data, NULL, fix_data, NULL, + NULL, &rbt_deserialized); + + /* Test to make sure we have a valid tree */ + ATF_REQUIRE(result == ISC_R_SUCCESS); + if (rbt_deserialized == NULL) + atf_tc_fail("deserialized rbt is null!"); /* Abort execution. */ + + check_test_data(rbt_deserialized); + + dns_rbt_printtext(rbt_deserialized, data_printer, stdout); + + dns_rbt_destroy(&rbt_deserialized); + munmap(base, filesize); + unlink("zone.bin"); + dns_test_end(); +} + +ATF_TC(deserialize_corrupt); +ATF_TC_HEAD(deserialize_corrupt, tc) { + atf_tc_set_md_var(tc, "descr", "Test reading a corrupt map file"); +} +ATF_TC_BODY(deserialize_corrupt, tc) { + dns_rbt_t *rbt = NULL; + isc_result_t result; + FILE *rbtfile = NULL; + off_t offset; + int fd; + off_t filesize = 0; + char *base, *p, *q; + uint32_t r; + int i; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Set up map file */ + result = dns_rbt_create(mctx, delete_data, NULL, &rbt); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + add_test_data(mctx, rbt); + rbtfile = fopen("./zone.bin", "w+b"); + ATF_REQUIRE(rbtfile != NULL); + result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL, + &offset); + ATF_REQUIRE(result == ISC_R_SUCCESS); + dns_rbt_destroy(&rbt); + + /* Read back with random fuzzing */ + for (i = 0; i < 256; i++) { + dns_rbt_t *rbt_deserialized = NULL; + + fd = open("zone.bin", O_RDWR); + isc_file_getsizefd(fd, &filesize); + base = mmap(NULL, filesize, + PROT_READ|PROT_WRITE, + MAP_FILE|MAP_PRIVATE, fd, 0); + ATF_REQUIRE(base != NULL && base != MAP_FAILED); + close(fd); + + /* Randomly fuzz a portion of the memory */ + isc_random_get(&r); + p = base + (r % filesize); + q = base + filesize; + isc_random_get(&r); + q -= (r % (q - p)); + while (p++ < q) { + isc_random_get(&r); + *p = r & 0xff; + } + + result = dns_rbt_deserialize_tree(base, filesize, 0, mctx, + delete_data, NULL, + fix_data, NULL, + NULL, &rbt_deserialized); + printf("%d: %s\n", i, isc_result_totext(result)); + + /* Test to make sure we have a valid tree */ + ATF_REQUIRE(result == ISC_R_SUCCESS || + result == ISC_R_INVALIDFILE); + if (result != ISC_R_SUCCESS) + ATF_REQUIRE(rbt_deserialized == NULL); + + if (rbt_deserialized != NULL) + dns_rbt_destroy(&rbt_deserialized); + + munmap(base, filesize); + } + + unlink("zone.bin"); + dns_test_end(); +} + + +ATF_TC(serialize_align); +ATF_TC_HEAD(serialize_align, tc) { + atf_tc_set_md_var(tc, "descr", + "Test the dns_rbt_serialize_align() function."); +} +ATF_TC_BODY(serialize_align, tc) { + UNUSED(tc); + + ATF_CHECK(dns_rbt_serialize_align(0) == 0); + ATF_CHECK(dns_rbt_serialize_align(1) == 8); + ATF_CHECK(dns_rbt_serialize_align(2) == 8); + ATF_CHECK(dns_rbt_serialize_align(3) == 8); + ATF_CHECK(dns_rbt_serialize_align(4) == 8); + ATF_CHECK(dns_rbt_serialize_align(5) == 8); + ATF_CHECK(dns_rbt_serialize_align(6) == 8); + ATF_CHECK(dns_rbt_serialize_align(7) == 8); + ATF_CHECK(dns_rbt_serialize_align(8) == 8); + ATF_CHECK(dns_rbt_serialize_align(9) == 16); + ATF_CHECK(dns_rbt_serialize_align(0xff) == 0x100); + ATF_CHECK(dns_rbt_serialize_align(0x301) == 0x308); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, serialize); + ATF_TP_ADD_TC(tp, deserialize_corrupt); + ATF_TP_ADD_TC(tp, serialize_align); + + return (atf_no_error()); +} diff --git a/lib/dns/tests/rbt_test.c b/lib/dns/tests/rbt_test.c new file mode 100644 index 0000000..81d97d4 --- /dev/null +++ b/lib/dns/tests/rbt_test.c @@ -0,0 +1,1437 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include <config.h> +#include <atf-c.h> +#include <isc/mem.h> +#include <isc/random.h> +#include <isc/string.h> +#include <fcntl.h> +#include <unistd.h> + +#include <inttypes.h> /* uintptr_t */ +#include <stdbool.h> + +#include <dns/rbt.h> +#include <dns/fixedname.h> +#include <dns/name.h> +#include <dns/result.h> +#include <dns/compress.h> +#include "dnstest.h" + +#include <isc/app.h> +#include <isc/buffer.h> +#include <isc/entropy.h> +#include <isc/file.h> +#include <isc/hash.h> +#include <isc/mem.h> +#include <isc/os.h> +#include <isc/string.h> +#include <isc/socket.h> +#include <isc/stdio.h> +#include <isc/task.h> +#include <isc/thread.h> +#include <isc/timer.h> +#include <isc/util.h> +#include <isc/print.h> +#include <isc/time.h> + +#include <dns/log.h> +#include <dns/name.h> +#include <dns/result.h> + +#include <dst/dst.h> + +#include <ctype.h> +#include <stdlib.h> +#include <time.h> + +typedef struct { + dns_rbt_t *rbt; + dns_rbt_t *rbt_distances; +} test_context_t; + +/* The initial structure of domain tree will be as follows: + * + * . + * | + * b + * / \ + * a d.e.f + * / | \ + * c | g.h + * | | + * w.y i + * / | \ \ + * x | z k + * | | + * p j + * / \ + * o q + */ + +/* The full absolute names of the nodes in the tree (the tree also + * contains "." which is not included in this list). + */ +static const char * const domain_names[] = { + "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f", + "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h" +}; + +static const size_t domain_names_count = (sizeof(domain_names) / + sizeof(domain_names[0])); + +/* These are set as the node data for the tree used in distances check + * (for the names in domain_names[] above). + */ +static const int node_distances[] = { + 3, 1, 2, 2, 2, 3, 1, 2, 1, 1, 2, 2 +}; + +/* + * The domain order should be: + * ., a, b, c, d.e.f, x.d.e.f, w.y.d.e.f, o.w.y.d.e.f, p.w.y.d.e.f, + * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h + * . (no data, can't be found) + * | + * b + * / \ + * a d.e.f + * / | \ + * c | g.h + * | | + * w.y i + * / | \ \ + * x | z k + * | | + * p j + * / \ + * o q + */ + +static const char * const ordered_names[] = { + "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f", + "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f", + "g.h", "i.g.h", "k.g.h"}; + +static const size_t ordered_names_count = (sizeof(ordered_names) / + sizeof(*ordered_names)); + +static void +delete_data(void *data, void *arg) { + UNUSED(arg); + + isc_mem_put(mctx, data, sizeof(size_t)); +} + +static test_context_t * +test_context_setup(void) { + test_context_t *ctx; + isc_result_t result; + size_t i; + + ctx = isc_mem_get(mctx, sizeof(*ctx)); + ATF_REQUIRE(ctx != NULL); + + ctx->rbt = NULL; + result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ctx->rbt_distances = NULL; + result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt_distances); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (i = 0; i < domain_names_count; i++) { + size_t *n; + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(domain_names[i], &fname); + + name = dns_fixedname_name(&fname); + + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + *n = i + 1; + result = dns_rbt_addname(ctx->rbt, name, n); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + *n = node_distances[i]; + result = dns_rbt_addname(ctx->rbt_distances, name, n); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + + return (ctx); +} + +static void +test_context_teardown(test_context_t *ctx) { + dns_rbt_destroy(&ctx->rbt); + dns_rbt_destroy(&ctx->rbt_distances); + + isc_mem_put(mctx, ctx, sizeof(*ctx)); +} + +/* + * Walk the tree and ensure that all the test nodes are present. + */ +static void +check_test_data(dns_rbt_t *rbt) { + dns_fixedname_t fixed; + isc_result_t result; + dns_name_t *foundname; + size_t i; + + foundname = dns_fixedname_initname(&fixed); + + for (i = 0; i < domain_names_count; i++) { + dns_fixedname_t fname; + dns_name_t *name; + size_t *n; + + dns_test_namefromstring(domain_names[i], &fname); + + name = dns_fixedname_name(&fname); + n = NULL; + result = dns_rbt_findname(rbt, name, 0, foundname, + (void *) &n); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(*n, i + 1); + } +} + +ATF_TC(rbt_create); +ATF_TC_HEAD(rbt_create, tc) { + atf_tc_set_md_var(tc, "descr", "Test the creation of an rbt"); +} +ATF_TC_BODY(rbt_create, tc) { + isc_result_t result; + test_context_t *ctx; + bool tree_ok; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ctx = test_context_setup(); + + check_test_data(ctx->rbt); + + tree_ok = dns__rbt_checkproperties(ctx->rbt); + ATF_CHECK_EQ(tree_ok, true); + + test_context_teardown(ctx); + + dns_test_end(); +} + +ATF_TC(rbt_nodecount); +ATF_TC_HEAD(rbt_nodecount, tc) { + atf_tc_set_md_var(tc, "descr", "Test dns_rbt_nodecount() on a tree"); +} +ATF_TC_BODY(rbt_nodecount, tc) { + isc_result_t result; + test_context_t *ctx; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ctx = test_context_setup(); + + ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt)); + + test_context_teardown(ctx); + + dns_test_end(); +} + +ATF_TC(rbtnode_get_distance); +ATF_TC_HEAD(rbtnode_get_distance, tc) { + atf_tc_set_md_var(tc, "descr", + "Test dns_rbtnode_get_distance() on a tree"); +} +ATF_TC_BODY(rbtnode_get_distance, tc) { + isc_result_t result; + test_context_t *ctx; + const char *name_str = "a"; + dns_fixedname_t fname; + dns_name_t *name; + dns_rbtnode_t *node = NULL; + dns_rbtnodechain_t chain; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ctx = test_context_setup(); + + dns_test_namefromstring(name_str, &fname); + name = dns_fixedname_name(&fname); + + dns_rbtnodechain_init(&chain, mctx); + + result = dns_rbt_findnode(ctx->rbt_distances, name, NULL, + &node, &chain, 0, NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + while (node != NULL) { + const size_t *distance = (const size_t *) node->data; + if (distance != NULL) + ATF_CHECK_EQ(*distance, + dns__rbtnode_getdistance(node)); + result = dns_rbtnodechain_next(&chain, NULL, NULL); + if (result == ISC_R_NOMORE) + break; + dns_rbtnodechain_current(&chain, NULL, NULL, &node); + } + + ATF_CHECK_EQ(result, ISC_R_NOMORE); + + dns_rbtnodechain_invalidate(&chain); + + test_context_teardown(ctx); + + dns_test_end(); +} + +ATF_TC(rbt_check_distance_random); +ATF_TC_HEAD(rbt_check_distance_random, tc) { + atf_tc_set_md_var(tc, "descr", + "Test tree balance, inserting names in random order"); +} +ATF_TC_BODY(rbt_check_distance_random, tc) { + /* This test checks an important performance-related property of + * the red-black tree, which is important for us: the longest + * path from a sub-tree's root to a node is no more than + * 2log(n). This check verifies that the tree is balanced. + */ + dns_rbt_t *mytree = NULL; + const unsigned int log_num_nodes = 16; + + int i; + isc_result_t result; + bool tree_ok; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + result = dns_rbt_create(mctx, delete_data, NULL, &mytree); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Names are inserted in random order. */ + + /* Make a large 65536 node top-level domain tree, i.e., the + * following code inserts names such as: + * + * savoucnsrkrqzpkqypbygwoiliawpbmz. + * wkadamcbbpjtundbxcmuayuycposvngx. + * wzbpznemtooxdpjecdxynsfztvnuyfao. + * yueojmhyffslpvfmgyfwioxegfhepnqq. + */ + for (i = 0; i < (1 << log_num_nodes); i++) { + size_t *n; + char namebuf[34]; + + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + *n = i + 1; + + while (1) { + int j; + dns_fixedname_t fname; + dns_name_t *name; + + for (j = 0; j < 32; j++) { + uint32_t v; + isc_random_get(&v); + namebuf[j] = 'a' + (v % 26); + } + namebuf[32] = '.'; + namebuf[33] = 0; + + dns_test_namefromstring(namebuf, &fname); + name = dns_fixedname_name(&fname); + + result = dns_rbt_addname(mytree, name, n); + if (result == ISC_R_SUCCESS) + break; + } + } + + /* 1 (root . node) + (1 << log_num_nodes) */ + ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree)); + + /* The distance from each node to its sub-tree root must be less + * than 2 * log(n). + */ + ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree)); + + /* Also check RB tree properties */ + tree_ok = dns__rbt_checkproperties(mytree); + ATF_CHECK_EQ(tree_ok, true); + + dns_rbt_destroy(&mytree); + + dns_test_end(); +} + +ATF_TC(rbt_check_distance_ordered); +ATF_TC_HEAD(rbt_check_distance_ordered, tc) { + atf_tc_set_md_var(tc, "descr", + "Test tree balance, inserting names in sorted order"); +} +ATF_TC_BODY(rbt_check_distance_ordered, tc) { + /* This test checks an important performance-related property of + * the red-black tree, which is important for us: the longest + * path from a sub-tree's root to a node is no more than + * 2log(n). This check verifies that the tree is balanced. + */ + dns_rbt_t *mytree = NULL; + const unsigned int log_num_nodes = 16; + + int i; + isc_result_t result; + bool tree_ok; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + result = dns_rbt_create(mctx, delete_data, NULL, &mytree); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Names are inserted in sorted order. */ + + /* Make a large 65536 node top-level domain tree, i.e., the + * following code inserts names such as: + * + * name00000000. + * name00000001. + * name00000002. + * name00000003. + */ + for (i = 0; i < (1 << log_num_nodes); i++) { + size_t *n; + char namebuf[14]; + dns_fixedname_t fname; + dns_name_t *name; + + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + *n = i + 1; + + snprintf(namebuf, sizeof(namebuf), "name%08x.", i); + dns_test_namefromstring(namebuf, &fname); + name = dns_fixedname_name(&fname); + + result = dns_rbt_addname(mytree, name, n); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + + /* 1 (root . node) + (1 << log_num_nodes) */ + ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree)); + + /* The distance from each node to its sub-tree root must be less + * than 2 * log(n). + */ + ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree)); + + /* Also check RB tree properties */ + tree_ok = dns__rbt_checkproperties(mytree); + ATF_CHECK_EQ(tree_ok, true); + + dns_rbt_destroy(&mytree); + + dns_test_end(); +} + +static isc_result_t +insert_helper(dns_rbt_t *rbt, const char *namestr, dns_rbtnode_t **node) { + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(namestr, &fname); + name = dns_fixedname_name(&fname); + + return (dns_rbt_addnode(rbt, name, node)); +} + +static bool +compare_labelsequences(dns_rbtnode_t *node, const char *labelstr) { + dns_name_t name; + isc_result_t result; + char *nodestr = NULL; + bool is_equal; + + dns_name_init(&name, NULL); + dns_rbt_namefromnode(node, &name); + + result = dns_name_tostring(&name, &nodestr, mctx); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + is_equal = strcmp(labelstr, nodestr) == 0 ? true : false; + + isc_mem_free(mctx, nodestr); + + return (is_equal); +} + +ATF_TC(rbt_insert); +ATF_TC_HEAD(rbt_insert, tc) { + atf_tc_set_md_var(tc, "descr", "Test insertion into a tree"); +} +ATF_TC_BODY(rbt_insert, tc) { + isc_result_t result; + test_context_t *ctx; + dns_rbtnode_t *node; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ctx = test_context_setup(); + + /* Check node count before beginning. */ + ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt)); + + /* Try to insert a node that already exists. */ + node = NULL; + result = insert_helper(ctx->rbt, "d.e.f", &node); + ATF_CHECK_EQ(result, ISC_R_EXISTS); + + /* Node count must not have changed. */ + ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt)); + + /* Try to insert a node that doesn't exist. */ + node = NULL; + result = insert_helper(ctx->rbt, "0", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(compare_labelsequences(node, "0"), true); + + /* Node count must have increased. */ + ATF_CHECK_EQ(16, dns_rbt_nodecount(ctx->rbt)); + + /* Another. */ + node = NULL; + result = insert_helper(ctx->rbt, "example.com", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE(node != NULL); + ATF_CHECK_EQ(node->data, NULL); + + /* Node count must have increased. */ + ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt)); + + /* Re-adding it should return EXISTS */ + node = NULL; + result = insert_helper(ctx->rbt, "example.com", &node); + ATF_CHECK_EQ(result, ISC_R_EXISTS); + + /* Node count must not have changed. */ + ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt)); + + /* Fission the node d.e.f */ + node = NULL; + result = insert_helper(ctx->rbt, "k.e.f", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(compare_labelsequences(node, "k"), true); + + /* Node count must have incremented twice ("d.e.f" fissioned to + * "d" and "e.f", and the newly added "k"). + */ + ATF_CHECK_EQ(19, dns_rbt_nodecount(ctx->rbt)); + + /* Fission the node "g.h" */ + node = NULL; + result = insert_helper(ctx->rbt, "h", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(compare_labelsequences(node, "h"), true); + + /* Node count must have incremented ("g.h" fissioned to "g" and + * "h"). + */ + ATF_CHECK_EQ(20, dns_rbt_nodecount(ctx->rbt)); + + /* Add child domains */ + + node = NULL; + result = insert_helper(ctx->rbt, "m.p.w.y.d.e.f", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(compare_labelsequences(node, "m"), true); + ATF_CHECK_EQ(21, dns_rbt_nodecount(ctx->rbt)); + + node = NULL; + result = insert_helper(ctx->rbt, "n.p.w.y.d.e.f", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(compare_labelsequences(node, "n"), true); + ATF_CHECK_EQ(22, dns_rbt_nodecount(ctx->rbt)); + + node = NULL; + result = insert_helper(ctx->rbt, "l.a", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(compare_labelsequences(node, "l"), true); + ATF_CHECK_EQ(23, dns_rbt_nodecount(ctx->rbt)); + + node = NULL; + result = insert_helper(ctx->rbt, "r.d.e.f", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + node = NULL; + result = insert_helper(ctx->rbt, "s.d.e.f", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(25, dns_rbt_nodecount(ctx->rbt)); + + node = NULL; + result = insert_helper(ctx->rbt, "h.w.y.d.e.f", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + /* Add more nodes one by one to cover left and right rotation + * functions. + */ + node = NULL; + result = insert_helper(ctx->rbt, "f", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "m", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "nm", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "om", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "k", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "l", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "fe", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "ge", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "i", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "ae", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "n", &node); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + test_context_teardown(ctx); + + dns_test_end(); +} + +ATF_TC(rbt_remove); +ATF_TC_HEAD(rbt_remove, tc) { + atf_tc_set_md_var(tc, "descr", "Test removal from a tree"); +} +ATF_TC_BODY(rbt_remove, tc) { + /* + * This testcase checks that after node removal, the + * binary-search tree is valid and all nodes that are supposed + * to exist are present in the correct order. It mainly tests + * DomainTree as a BST, and not particularly as a red-black + * tree. This test checks node deletion when upper nodes have + * data. + */ + isc_result_t result; + size_t j; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Delete single nodes and check if the rest of the nodes exist. + */ + for (j = 0; j < ordered_names_count; j++) { + dns_rbt_t *mytree = NULL; + dns_rbtnode_t *node; + size_t i; + size_t *n; + bool tree_ok; + dns_rbtnodechain_t chain; + size_t start_node; + + /* Create a tree. */ + result = dns_rbt_create(mctx, delete_data, NULL, &mytree); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Insert test data into the tree. */ + for (i = 0; i < domain_names_count; i++) { + node = NULL; + result = insert_helper(mytree, domain_names[i], &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + + /* Check that all names exist in order. */ + for (i = 0; i < ordered_names_count; i++) { + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(ordered_names[i], &fname); + + name = dns_fixedname_name(&fname); + node = NULL; + result = dns_rbt_findnode(mytree, name, NULL, + &node, NULL, + DNS_RBTFIND_EMPTYDATA, + NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + /* Add node data */ + ATF_REQUIRE(node != NULL); + ATF_REQUIRE_EQ(node->data, NULL); + + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + *n = i; + + node->data = n; + } + + /* Now, delete the j'th node from the tree. */ + { + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(ordered_names[j], &fname); + + name = dns_fixedname_name(&fname); + + result = dns_rbt_deletename(mytree, name, false); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + } + + /* Check RB tree properties. */ + tree_ok = dns__rbt_checkproperties(mytree); + ATF_CHECK_EQ(tree_ok, true); + + dns_rbtnodechain_init(&chain, mctx); + + /* Now, walk through nodes in order. */ + if (j == 0) { + /* + * Node for ordered_names[0] was already deleted + * above. We start from node 1. + */ + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(ordered_names[0], &fname); + name = dns_fixedname_name(&fname); + node = NULL; + result = dns_rbt_findnode(mytree, name, NULL, + &node, NULL, + 0, + NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_NOTFOUND); + + dns_test_namefromstring(ordered_names[1], &fname); + name = dns_fixedname_name(&fname); + node = NULL; + result = dns_rbt_findnode(mytree, name, NULL, + &node, &chain, + 0, + NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + start_node = 1; + } else { + /* Start from node 0. */ + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(ordered_names[0], &fname); + name = dns_fixedname_name(&fname); + node = NULL; + result = dns_rbt_findnode(mytree, name, NULL, + &node, &chain, + 0, + NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + start_node = 0; + } + + /* + * node and chain have been set by the code above at + * this point. + */ + for (i = start_node; i < ordered_names_count; i++) { + dns_fixedname_t fname_j, fname_i; + dns_name_t *name_j, *name_i; + + dns_test_namefromstring(ordered_names[j], &fname_j); + name_j = dns_fixedname_name(&fname_j); + dns_test_namefromstring(ordered_names[i], &fname_i); + name_i = dns_fixedname_name(&fname_i); + + if (dns_name_equal(name_i, name_j)) { + /* + * This may be true for the last node if + * we seek ahead in the loop using + * dns_rbtnodechain_next() below. + */ + if (node == NULL) { + break; + } + + /* All ordered nodes have data + * initially. If any node is empty, it + * means it was removed, but an empty + * node exists because it is a + * super-domain. Just skip it. + */ + if (node->data == NULL) { + result = dns_rbtnodechain_next(&chain, + NULL, + NULL); + if (result == ISC_R_NOMORE) { + node = NULL; + } else { + dns_rbtnodechain_current(&chain, + NULL, + NULL, + &node); + } + } + continue; + } + + ATF_REQUIRE(node != NULL); + + n = (size_t *) node->data; + if (n != NULL) { + /* printf("n=%zu, i=%zu\n", *n, i); */ + ATF_CHECK_EQ(*n, i); + } + + result = dns_rbtnodechain_next(&chain, NULL, NULL); + if (result == ISC_R_NOMORE) { + node = NULL; + } else { + dns_rbtnodechain_current(&chain, NULL, NULL, + &node); + } + } + + /* We should have reached the end of the tree. */ + ATF_REQUIRE_EQ(node, NULL); + + dns_rbt_destroy(&mytree); + } + + dns_test_end(); +} + +static void +insert_nodes(dns_rbt_t *mytree, char **names, + size_t *names_count, uint32_t num_names) +{ + uint32_t i; + dns_rbtnode_t *node; + + for (i = 0; i < num_names; i++) { + size_t *n; + char namebuf[34]; + + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + + *n = i; /* Unused value */ + + while (1) { + int j; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result; + + for (j = 0; j < 32; j++) { + uint32_t v; + isc_random_get(&v); + namebuf[j] = 'a' + (v % 26); + } + namebuf[32] = '.'; + namebuf[33] = 0; + + dns_test_namefromstring(namebuf, &fname); + name = dns_fixedname_name(&fname); + + node = NULL; + result = dns_rbt_addnode(mytree, name, &node); + if (result == ISC_R_SUCCESS) { + node->data = n; + names[*names_count] = isc_mem_strdup(mctx, + namebuf); + ATF_REQUIRE(names[*names_count] != NULL); + *names_count += 1; + break; + } + } + } +} + +static void +remove_nodes(dns_rbt_t *mytree, char **names, + size_t *names_count, uint32_t num_names) +{ + uint32_t i; + + UNUSED(mytree); + + for (i = 0; i < num_names; i++) { + uint32_t node; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result; + + isc_random_get(&node); + + node %= *names_count; + + dns_test_namefromstring(names[node], &fname); + name = dns_fixedname_name(&fname); + + result = dns_rbt_deletename(mytree, name, false); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + isc_mem_free(mctx, names[node]); + if (*names_count > 0) { + names[node] = names[*names_count - 1]; + names[*names_count - 1] = NULL; + *names_count -= 1; + } + } +} + +static void +check_tree(dns_rbt_t *mytree, char **names, size_t names_count, + unsigned int line) +{ + bool tree_ok; + + UNUSED(names); + + ATF_CHECK_EQ_MSG(names_count + 1, dns_rbt_nodecount(mytree), + "line:%u: %lu != %u", line, + (unsigned long)(names_count + 1), + dns_rbt_nodecount(mytree)); + + /* + * The distance from each node to its sub-tree root must be less + * than 2 * log_2(1024). + */ + ATF_CHECK((2 * 10) >= dns__rbt_getheight(mytree)); + + /* Also check RB tree properties */ + tree_ok = dns__rbt_checkproperties(mytree); + ATF_CHECK_EQ(tree_ok, true); +} + +ATF_TC(rbt_insert_and_remove); +ATF_TC_HEAD(rbt_insert_and_remove, tc) { + atf_tc_set_md_var(tc, "descr", + "Test insert and remove in a loop"); +} +ATF_TC_BODY(rbt_insert_and_remove, tc) { + /* + * What is the best way to test our red-black tree code? It is + * not a good method to test every case handled in the actual + * code itself. This is because our approach itself may be + * incorrect. + * + * We test our code at the interface level here by exercising the + * tree randomly multiple times, checking that red-black tree + * properties are valid, and all the nodes that are supposed to be + * in the tree exist and are in order. + * + * NOTE: These tests are run within a single tree level in the + * forest. The number of nodes in the tree level doesn't grow + * over 1024. + */ + isc_result_t result; + dns_rbt_t *mytree = NULL; + size_t *n; + /* + * We use an array for storing names instead of a set + * structure. It's slow, but works and is good enough for tests. + */ + char *names[1024]; + size_t names_count; + int i; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + result = dns_rbt_create(mctx, delete_data, NULL, &mytree); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + result = dns_rbt_addname(mytree, dns_rootname, n); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + memset(names, 0, sizeof(names)); + names_count = 0; + + /* Repeat the insert/remove test some 4096 times */ + for (i = 0; i < 4096; i++) { + uint32_t num_names; + isc_random_get(&num_names); + + if (names_count < 1024) { + num_names %= 1024 - names_count; + num_names++; + } else { + num_names = 0; + } + + insert_nodes(mytree, names, &names_count, num_names); + check_tree(mytree, names, names_count, __LINE__); + + isc_random_get(&num_names); + if (names_count > 0) { + num_names %= names_count; + num_names++; + } else { + num_names = 0; + } + + remove_nodes(mytree, names, &names_count, num_names); + check_tree(mytree, names, names_count, __LINE__); + } + + /* Remove the rest of the nodes */ + remove_nodes(mytree, names, &names_count, names_count); + check_tree(mytree, names, names_count, __LINE__); + + for (i = 0; i < 1024; i++) { + if (names[i] != NULL) { + isc_mem_free(mctx, names[i]); + } + } + + result = dns_rbt_deletename(mytree, dns_rootname, false); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "result: %s", isc_result_totext(result)); + ATF_CHECK_EQ_MSG(dns_rbt_nodecount(mytree), 0, + "%u != 0", dns_rbt_nodecount(mytree)); + + dns_rbt_destroy(&mytree); + + dns_test_end(); +} + +ATF_TC(rbt_findname); +ATF_TC_HEAD(rbt_findname, tc) { + atf_tc_set_md_var(tc, "descr", "findname return values"); +} +ATF_TC_BODY(rbt_findname, tc) { + isc_result_t result; + test_context_t *ctx = NULL; + dns_fixedname_t fname, found; + dns_name_t *name = NULL, *foundname = NULL; + size_t *n = NULL; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ctx = test_context_setup(); + + /* Try to find a name that exists. */ + dns_test_namefromstring("d.e.f", &fname); + name = dns_fixedname_name(&fname); + + foundname = dns_fixedname_initname(&found); + + result = dns_rbt_findname(ctx->rbt, name, + DNS_RBTFIND_EMPTYDATA, + foundname, (void *) &n); + ATF_CHECK(dns_name_equal(foundname, name)); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + /* Now without EMPTYDATA */ + result = dns_rbt_findname(ctx->rbt, name, 0, + foundname, (void *) &n); + ATF_CHECK_EQ(result, ISC_R_NOTFOUND); + + /* Now one that partially matches */ + dns_test_namefromstring("d.e.f.g.h.i.j", &fname); + name = dns_fixedname_name(&fname); + result = dns_rbt_findname(ctx->rbt, name, + DNS_RBTFIND_EMPTYDATA, + foundname, (void *) &n); + ATF_CHECK_EQ(result, DNS_R_PARTIALMATCH); + + /* Now one that doesn't match */ + dns_test_namefromstring("1.2", &fname); + name = dns_fixedname_name(&fname); + result = dns_rbt_findname(ctx->rbt, name, + DNS_RBTFIND_EMPTYDATA, + foundname, (void *) &n); + ATF_CHECK_EQ(result, DNS_R_PARTIALMATCH); + ATF_CHECK(dns_name_equal(foundname, dns_rootname)); + + test_context_teardown(ctx); + + dns_test_end(); +} + +ATF_TC(rbt_addname); +ATF_TC_HEAD(rbt_addname, tc) { + atf_tc_set_md_var(tc, "descr", "addname return values"); +} +ATF_TC_BODY(rbt_addname, tc) { + isc_result_t result; + test_context_t *ctx = NULL; + dns_fixedname_t fname; + dns_name_t *name = NULL; + size_t *n; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ctx = test_context_setup(); + + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + *n = 1; + + dns_test_namefromstring("d.e.f.g.h.i.j.k", &fname); + name = dns_fixedname_name(&fname); + + /* Add a name that doesn't exist */ + result = dns_rbt_addname(ctx->rbt, name, n); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Now add again, should get ISC_R_EXISTS */ + n = isc_mem_get(mctx, sizeof(size_t)); + ATF_REQUIRE(n != NULL); + *n = 2; + result = dns_rbt_addname(ctx->rbt, name, n); + ATF_REQUIRE_EQ(result, ISC_R_EXISTS); + isc_mem_put(mctx, n, sizeof(size_t)); + + test_context_teardown(ctx); + + dns_test_end(); +} + +ATF_TC(rbt_deletename); +ATF_TC_HEAD(rbt_deletename, tc) { + atf_tc_set_md_var(tc, "descr", "deletename return values"); +} +ATF_TC_BODY(rbt_deletename, tc) { + isc_result_t result; + test_context_t *ctx = NULL; + dns_fixedname_t fname; + dns_name_t *name = NULL; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ctx = test_context_setup(); + + /* Delete a name that doesn't exist */ + dns_test_namefromstring("z.x.y.w", &fname); + name = dns_fixedname_name(&fname); + result = dns_rbt_deletename(ctx->rbt, name, false); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + + /* Now one that does */ + dns_test_namefromstring("d.e.f", &fname); + name = dns_fixedname_name(&fname); + result = dns_rbt_deletename(ctx->rbt, name, false); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + + test_context_teardown(ctx); + + dns_test_end(); +} + +ATF_TC(rbt_nodechain); +ATF_TC_HEAD(rbt_nodechain, tc) { + atf_tc_set_md_var(tc, "descr", "nodechain"); +} +ATF_TC_BODY(rbt_nodechain, tc) { + isc_result_t result; + test_context_t *ctx; + dns_fixedname_t fname, found, expect; + dns_name_t *name, *foundname, *expected; + dns_rbtnode_t *node = NULL; + dns_rbtnodechain_t chain; + + UNUSED(tc); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_test_begin(NULL, true); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ctx = test_context_setup(); + + dns_rbtnodechain_init(&chain, mctx); + + dns_test_namefromstring("a", &fname); + name = dns_fixedname_name(&fname); + + result = dns_rbt_findnode(ctx->rbt, name, NULL, + &node, &chain, 0, NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + foundname = dns_fixedname_initname(&found); + + dns_test_namefromstring("a", &expect); + expected = dns_fixedname_name(&expect); + UNUSED(expected); + + result = dns_rbtnodechain_first(&chain, ctx->rbt, foundname, NULL); + ATF_CHECK_EQ(result, DNS_R_NEWORIGIN); + ATF_CHECK_EQ(dns_name_countlabels(foundname), 0); + + result = dns_rbtnodechain_prev(&chain, NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_NOMORE); + + result = dns_rbtnodechain_next(&chain, NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + result = dns_rbtnodechain_next(&chain, NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + result = dns_rbtnodechain_last(&chain, ctx->rbt, NULL, NULL); + ATF_CHECK_EQ(result, DNS_R_NEWORIGIN); + + result = dns_rbtnodechain_next(&chain, NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_NOMORE); + + result = dns_rbtnodechain_last(&chain, ctx->rbt, NULL, NULL); + ATF_CHECK_EQ(result, DNS_R_NEWORIGIN); + + result = dns_rbtnodechain_prev(&chain, NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + dns_rbtnodechain_invalidate(&chain); + + test_context_teardown(ctx); + + dns_test_end(); +} + +#ifdef ISC_PLATFORM_USETHREADS +#ifdef DNS_BENCHMARK_TESTS + +/* + * XXXMUKS: Don't delete this code. It is useful in benchmarking the + * RBT, but we don't require it as part of the unit test runs. + */ + +ATF_TC(benchmark); +ATF_TC_HEAD(benchmark, tc) { + atf_tc_set_md_var(tc, "descr", "Benchmark RBT implementation"); +} + +static dns_fixedname_t *fnames; +static dns_name_t **names; +static int *values; + +static void * +find_thread(void *arg) { + dns_rbt_t *mytree; + isc_result_t result; + dns_rbtnode_t *node; + unsigned int j, i; + unsigned int start = 0; + + mytree = (dns_rbt_t *) arg; + while (start == 0) + start = random() % 4000000; + + /* Query 32 million random names from it in each thread */ + for (j = 0; j < 8; j++) { + for (i = start; i != start - 1; i = (i + 1) % 4000000) { + node = NULL; + result = dns_rbt_findnode(mytree, names[i], NULL, + &node, NULL, + DNS_RBTFIND_EMPTYDATA, + NULL, NULL); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE(node != NULL); + ATF_CHECK_EQ(values[i], (intptr_t) node->data); + } + } + + return (NULL); +} + +ATF_TC_BODY(benchmark, tc) { + isc_result_t result; + char namestr[sizeof("name18446744073709551616.example.org.")]; + unsigned int r; + dns_rbt_t *mytree; + dns_rbtnode_t *node; + unsigned int i; + unsigned int maxvalue = 1000000; + isc_time_t ts1, ts2; + double t; + unsigned int nthreads; + isc_thread_t threads[32]; + + UNUSED(tc); + + srandom(time(NULL)); + + debug_mem_record = false; + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + fnames = (dns_fixedname_t *) malloc(4000000 * sizeof(dns_fixedname_t)); + names = (dns_name_t **) malloc(4000000 * sizeof(dns_name_t *)); + values = (int *) malloc(4000000 * sizeof(int)); + + for (i = 0; i < 4000000; i++) { + r = ((unsigned long) random()) % maxvalue; + snprintf(namestr, sizeof(namestr), "name%u.example.org.", r); + dns_test_namefromstring(namestr, &fnames[i]); + names[i] = dns_fixedname_name(&fnames[i]); + values[i] = r; + } + + /* Create a tree. */ + mytree = NULL; + result = dns_rbt_create(mctx, NULL, NULL, &mytree); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Insert test data into the tree. */ + for (i = 0; i < maxvalue; i++) { + snprintf(namestr, sizeof(namestr), "name%u.example.org.", i); + node = NULL; + result = insert_helper(mytree, namestr, &node); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + node->data = (void *) (intptr_t) i; + } + + result = isc_time_now(&ts1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + nthreads = ISC_MIN(isc_os_ncpus(), 32); + nthreads = ISC_MAX(nthreads, 1); + for (i = 0; i < nthreads; i++) { + result = isc_thread_create(find_thread, mytree, &threads[i]); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + + for (i = 0; i < nthreads; i++) { + result = isc_thread_join(threads[i], NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + } + + result = isc_time_now(&ts2); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + t = isc_time_microdiff(&ts2, &ts1); + + printf("%u findnode calls, %f seconds, %f calls/second\n", + nthreads * 8 * 4000000, t / 1000000.0, + (nthreads * 8 * 4000000) / (t / 1000000.0)); + + free(values); + free(names); + free(fnames); + + dns_rbt_destroy(&mytree); + + dns_test_end(); +} + +#endif /* DNS_BENCHMARK_TESTS */ +#endif /* ISC_PLATFORM_USETHREADS */ + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, rbt_create); + ATF_TP_ADD_TC(tp, rbt_nodecount); + ATF_TP_ADD_TC(tp, rbtnode_get_distance); + ATF_TP_ADD_TC(tp, rbt_check_distance_random); + ATF_TP_ADD_TC(tp, rbt_check_distance_ordered); + ATF_TP_ADD_TC(tp, rbt_insert); + ATF_TP_ADD_TC(tp, rbt_remove); + ATF_TP_ADD_TC(tp, rbt_insert_and_remove); + ATF_TP_ADD_TC(tp, rbt_findname); + ATF_TP_ADD_TC(tp, rbt_addname); + ATF_TP_ADD_TC(tp, rbt_deletename); + ATF_TP_ADD_TC(tp, rbt_nodechain); +#ifdef ISC_PLATFORM_USETHREADS +#ifdef DNS_BENCHMARK_TESTS + ATF_TP_ADD_TC(tp, benchmark); +#endif /* DNS_BENCHMARK_TESTS */ +#endif /* ISC_PLATFORM_USETHREADS */ + + return (atf_no_error()); +} diff --git a/lib/dns/tests/rdata_test.c b/lib/dns/tests/rdata_test.c new file mode 100644 index 0000000..6837516 --- /dev/null +++ b/lib/dns/tests/rdata_test.c @@ -0,0 +1,1214 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdbool.h> +#include <unistd.h> + +#include <isc/hex.h> +#include <isc/lex.h> +#include <isc/types.h> + +#include <dns/callbacks.h> +#include <dns/rdata.h> + +#include "dnstest.h" + +/***** + ***** Commonly used structures + *****/ + +/* + * An array of these structures is passed to check_text_ok(). + */ +struct text_ok { + const char *text_in; /* text passed to fromtext_*() */ + const char *text_out; /* text expected from totext_*(); + NULL indicates text_in is invalid */ + int lineno; /* source line defining this RDATA */ +}; +typedef struct text_ok text_ok_t; + +/* + * An array of these structures is passed to check_wire_ok(). + */ +struct wire_ok { + unsigned char data[512]; /* RDATA in wire format */ + size_t len; /* octets of data to parse */ + bool ok; /* is this RDATA valid? */ + int lineno; /* source line defining this RDATA */ +}; +typedef struct wire_ok wire_ok_t; + +/***** + ***** Convenience macros for creating the above structures + *****/ + +#define TEXT_VALID_CHANGED(data_in, data_out) \ + { data_in, data_out, __LINE__ } +#define TEXT_VALID(data) { data, data, __LINE__ } +#define TEXT_INVALID(data) { data, NULL, __LINE__ } +#define TEXT_SENTINEL() TEXT_INVALID(NULL) + +#define VARGC(...) (sizeof((unsigned char[]){ __VA_ARGS__ })) +#define WIRE_TEST(ok, ...) { \ + { __VA_ARGS__ }, VARGC(__VA_ARGS__), \ + ok, __LINE__ \ + } +#define WIRE_VALID(...) WIRE_TEST(true, __VA_ARGS__) +#define WIRE_INVALID(...) WIRE_TEST(false, __VA_ARGS__) +#define WIRE_SENTINEL() WIRE_TEST(false) + +/***** + ***** Checking functions used by test cases + *****/ + +/* + * Test whether converting rdata to a type-specific struct and then back to + * rdata results in the same uncompressed wire form. This checks whether + * tostruct_*() and fromstruct_*() routines for given RR class and type behave + * consistently. + * + * This function is called for every correctly processed input RDATA, from both + * check_text_ok_single() and check_wire_ok_single(). + */ +static void +check_struct_conversions(dns_rdata_t *rdata, size_t structsize, int lineno) { + dns_rdataclass_t rdclass = rdata->rdclass; + dns_rdatatype_t type = rdata->type; + isc_result_t result; + isc_buffer_t target; + void *rdata_struct; + char buf[1024], hex[BUFSIZ]; + + rdata_struct = isc_mem_allocate(mctx, structsize); + ATF_REQUIRE(rdata_struct != NULL); + + /* + * Convert from uncompressed wire form into type-specific struct. + */ + result = dns_rdata_tostruct(rdata, rdata_struct, NULL); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "%s (%u): dns_rdata_tostruct() failed", + dns_test_tohex(rdata->data, rdata->length, + hex, sizeof(hex)), + rdata->length); + /* + * Convert from type-specific struct into uncompressed wire form. + */ + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_rdata_fromstruct(NULL, rdclass, type, rdata_struct, + &target); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "line %d: %s (%u): dns_rdata_fromstruct() failed", + lineno, dns_test_tohex(rdata->data, rdata->length, + hex, sizeof(hex)), + rdata->length); + /* + * Ensure results are consistent. + */ + ATF_REQUIRE_EQ_MSG(isc_buffer_usedlength(&target), rdata->length, + "line %d: %s (%u): wire form data length changed " + "after converting to type-specific struct and back", + lineno, dns_test_tohex(rdata->data, rdata->length, + hex, sizeof(hex)), + rdata->length); + ATF_REQUIRE_EQ_MSG(memcmp(buf, rdata->data, rdata->length), 0, + "line %d: %s (%u): wire form data different after " + "converting to type-specific struct and back", + lineno, dns_test_tohex(rdata->data, rdata->length, + hex, sizeof(hex)), + rdata->length); + + isc_mem_free(mctx, rdata_struct); +} + +/* + * Check whether converting supplied text form RDATA into uncompressed wire + * form succeeds (tests fromtext_*()). If so, try converting it back into text + * form and see if it results in the original text (tests totext_*()). + */ +static void +check_text_ok_single(const text_ok_t *text_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) +{ + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned char buf_fromtext[1024]; + char buf_totext[1024] = { 0 }; + isc_buffer_t target; + isc_result_t result; + + /* + * Try converting text form RDATA into uncompressed wire form. + */ + result = dns_test_rdatafromstring(&rdata, rdclass, type, buf_fromtext, + sizeof(buf_fromtext), + text_ok->text_in); + /* + * Check whether result is as expected. + */ + if (text_ok->text_out != NULL) { + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "line %d: '%s': " + "expected success, got failure", + text_ok->lineno, text_ok->text_in); + } else { + ATF_REQUIRE_MSG(result != ISC_R_SUCCESS, + "line %d: '%s': " + "expected failure, got success", + text_ok->lineno, text_ok->text_in); + } + /* + * If text form RDATA was not parsed correctly, performing any + * additional checks is pointless. + */ + if (result != ISC_R_SUCCESS) { + return; + } + /* + * Try converting uncompressed wire form RDATA back into text form and + * check whether the resulting text is the same as the original one. + */ + isc_buffer_init(&target, buf_totext, sizeof(buf_totext)); + result = dns_rdata_totext(&rdata, NULL, &target); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "line %d: '%s': " + "failed to convert rdata back to text form", + text_ok->lineno, text_ok->text_in); + ATF_REQUIRE_EQ_MSG(strcmp(buf_totext, text_ok->text_out), 0, + "line %d: '%s': " + "converts back to '%s', expected '%s'", + text_ok->lineno, text_ok->text_in, buf_totext, + text_ok->text_out); + /* + * Perform two-way conversion checks between uncompressed wire form and + * type-specific struct. + */ + check_struct_conversions(&rdata, structsize, text_ok->lineno); +} + +/* + * Test whether supplied wire form RDATA is properly handled as being either + * valid or invalid for an RR of given rdclass and type. + */ +static void +check_wire_ok_single(const wire_ok_t *wire_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) +{ + isc_buffer_t source, target; + unsigned char buf[1024]; + dns_decompress_t dctx; + isc_result_t result; + dns_rdata_t rdata; + char hex[BUFSIZ]; + + /* + * Set up len-octet buffer pointing at data. + */ + isc_buffer_constinit(&source, wire_ok->data, wire_ok->len); + isc_buffer_add(&source, wire_ok->len); + isc_buffer_setactive(&source, wire_ok->len); + /* + * Initialize target structures. + */ + isc_buffer_init(&target, buf, sizeof(buf)); + dns_rdata_init(&rdata); + /* + * Try converting wire data into uncompressed wire form. + */ + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); + result = dns_rdata_fromwire(&rdata, rdclass, type, &source, &dctx, 0, + &target); + dns_decompress_invalidate(&dctx); + /* + * Check whether result is as expected. + */ + if (wire_ok->ok) { + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "line %d: %s (%lu): " + "expected success, got failure", + wire_ok->lineno, + dns_test_tohex(wire_ok->data, wire_ok->len, + hex, sizeof(hex)), + (unsigned long)wire_ok->len); + } else { + ATF_REQUIRE_MSG(result != ISC_R_SUCCESS, + "line %d: %s (%lu): " + "expected failure, got success", + wire_ok->lineno, + dns_test_tohex(wire_ok->data, wire_ok->len, + hex, sizeof(hex)), + (unsigned long)wire_ok->len); + } + /* + * If data was parsed correctly, perform two-way conversion checks + * between uncompressed wire form and type-specific struct. + */ + if (result == ISC_R_SUCCESS) { + check_struct_conversions(&rdata, structsize, wire_ok->lineno); + } +} + +/* + * Test fromtext_*() and totext_*() routines for given RR class and type for + * each text form RDATA in the supplied array. See the comment for + * check_text_ok_single() for an explanation of how exactly these routines are + * tested. + */ +static void +check_text_ok(const text_ok_t *text_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) +{ + size_t i; + + /* + * Check all entries in the supplied array. + */ + for (i = 0; text_ok[i].text_in != NULL; i++) { + check_text_ok_single(&text_ok[i], rdclass, type, structsize); + } +} + +/* + * For each wire form RDATA in the supplied array, check whether it is properly + * handled as being either valid or invalid for an RR of given rdclass and + * type, then check whether trying to process a zero-length wire data buffer + * yields the expected result. This checks whether the fromwire_*() routine + * for given RR class and type behaves as expected. + */ +static void +check_wire_ok(const wire_ok_t *wire_ok, bool empty_ok, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + size_t structsize) +{ + wire_ok_t empty_wire = WIRE_TEST(empty_ok); + size_t i; + + /* + * Check all entries in the supplied array. + */ + for (i = 0; wire_ok[i].len != 0; i++) { + check_wire_ok_single(&wire_ok[i], rdclass, type, structsize); + } + + /* + * Check empty wire data. + */ + check_wire_ok_single(&empty_wire, rdclass, type, structsize); +} + +/* + * Test whether supplied sets of text form and/or wire form RDATA are handled + * as expected. This is just a helper function which should be the only + * function called for a test case using it, due to the use of dns_test_begin() + * and dns_test_end(). + * + * The empty_ok argument denotes whether an attempt to parse a zero-length wire + * data buffer should succeed or not (it is valid for some RR types). There is + * no point in performing a similar check for empty text form RDATA, because + * dns_rdata_fromtext() returns ISC_R_UNEXPECTEDEND before calling fromtext_*() + * for the given RR class and type. + */ +static void +check_rdata(const text_ok_t *text_ok, const wire_ok_t *wire_ok, + bool empty_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) +{ + isc_result_t result; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + if (text_ok != NULL) { + check_text_ok(text_ok, rdclass, type, structsize); + } + if (wire_ok != NULL) { + check_wire_ok(wire_ok, empty_ok, rdclass, type, structsize); + } + + dns_test_end(); +} + +/***** + ***** Individual unit tests + *****/ + +/* + * CSYNC tests. + * + * RFC 7477: + * + * 2.1. The CSYNC Resource Record Format + * + * 2.1.1. The CSYNC Resource Record Wire Format + * + * The CSYNC RDATA consists of the following fields: + * + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SOA Serial | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | Type Bit Map / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * / Type Bit Map (continued) / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 2.1.1.1. The SOA Serial Field + * + * The SOA Serial field contains a copy of the 32-bit SOA serial number + * from the child zone. If the soaminimum flag is set, parental agents + * querying children's authoritative servers MUST NOT act on data from + * zones advertising an SOA serial number less than this value. See + * [RFC1982] for properly implementing "less than" logic. If the + * soaminimum flag is not set, parental agents MUST ignore the value in + * the SOA Serial field. Clients can set the field to any value if the + * soaminimum flag is unset, such as the number zero. + * + * (...) + * + * 2.1.1.2. The Flags Field + * + * The Flags field contains 16 bits of boolean flags that define + * operations that affect the processing of the CSYNC record. The flags + * defined in this document are as follows: + * + * 0x00 0x01: "immediate" + * + * 0x00 0x02: "soaminimum" + * + * The definitions for how the flags are to be used can be found in + * Section 3. + * + * The remaining flags are reserved for use by future specifications. + * Undefined flags MUST be set to 0 by CSYNC publishers. Parental + * agents MUST NOT process a CSYNC record if it contains a 1 value for a + * flag that is unknown to or unsupported by the parental agent. + * + * 2.1.1.2.1. The Type Bit Map Field + * + * The Type Bit Map field indicates the record types to be processed by + * the parental agent, according to the procedures in Section 3. The + * Type Bit Map field is encoded in the same way as the Type Bit Map + * field of the NSEC record, described in [RFC4034], Section 4.1.2. If + * a bit has been set that a parental agent implementation does not + * understand, the parental agent MUST NOT act upon the record. + * Specifically, a parental agent must not simply copy the data, and it + * must understand the semantics associated with a bit in the Type Bit + * Map field that has been set to 1. + */ +ATF_TC(csync); +ATF_TC_HEAD(csync, tc) { + atf_tc_set_md_var(tc, "descr", "CSYNC RDATA manipulations"); +} +ATF_TC_BODY(csync, tc) { + text_ok_t text_ok[] = { + TEXT_INVALID(""), + TEXT_INVALID("0"), + TEXT_VALID("0 0"), + TEXT_VALID("0 0 A"), + TEXT_VALID("0 0 NS"), + TEXT_VALID("0 0 AAAA"), + TEXT_VALID("0 0 A AAAA"), + TEXT_VALID("0 0 A NS AAAA"), + TEXT_INVALID("0 0 A NS AAAA BOGUS"), + TEXT_SENTINEL() + }; + wire_ok_t wire_ok[] = { + /* + * Short. + */ + WIRE_INVALID(0x00), + /* + * Short. + */ + WIRE_INVALID(0x00, 0x00), + /* + * Short. + */ + WIRE_INVALID(0x00, 0x00, 0x00), + /* + * Short. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00), + /* + * Short. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00), + /* + * Serial + flags only. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + /* + * Bad type map. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + /* + * Bad type map. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + /* + * Good type map. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x02), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + UNUSED(tc); + + check_rdata(text_ok, wire_ok, false, dns_rdataclass_in, + dns_rdatatype_csync, sizeof(dns_rdata_csync_t)); +} + +/* + * DOA tests. + * + * draft-durand-doa-over-dns-03: + * + * 3.2. DOA RDATA Wire Format + * + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 0: | | + * | DOA-ENTERPRISE | + * | | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 4: | | + * | DOA-TYPE | + * | | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 8: | DOA-LOCATION | DOA-MEDIA-TYPE / + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 10: / / + * / DOA-MEDIA-TYPE (continued) / + * / / + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * / / + * / DOA-DATA / + * / / + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * DOA-ENTERPRISE: a 32-bit unsigned integer in network order. + * + * DOA-TYPE: a 32-bit unsigned integer in network order. + * + * DOA-LOCATION: an 8-bit unsigned integer. + * + * DOA-MEDIA-TYPE: A <character-string> (see [RFC1035]). The first + * octet of the <character-string> contains the number of characters to + * follow. + * + * DOA-DATA: A variable length blob of binary data. The length of the + * DOA-DATA is not contained within the wire format of the RR and has to + * be computed from the RDLENGTH of the entire RR once other fields have + * been taken into account. + * + * 3.3. DOA RDATA Presentation Format + * + * The DOA-ENTERPRISE field is presented as an unsigned 32-bit decimal + * integer with range 0 - 4,294,967,295. + * + * The DOA-TYPE field is presented as an unsigned 32-bit decimal integer + * with range 0 - 4,294,967,295. + * + * The DOA-LOCATION field is presented as an unsigned 8-bit decimal + * integer with range 0 - 255. + * + * The DOA-MEDIA-TYPE field is presented as a single <character-string>. + * + * The DOA-DATA is presented as Base64 encoded data [RFC4648] unless the + * DOA-DATA is empty in which case it is presented as a single dash + * character ("-", ASCII 45). White space is permitted within Base64 + * data. + */ +ATF_TC(doa); +ATF_TC_HEAD(doa, tc) { + atf_tc_set_md_var(tc, "descr", "DOA RDATA manipulations"); +} +ATF_TC_BODY(doa, tc) { + text_ok_t text_ok[] = { + /* + * Valid, non-empty DOA-DATA. + */ + TEXT_VALID("0 0 1 \"text/plain\" Zm9v"), + /* + * Valid, non-empty DOA-DATA with whitespace in between. + */ + TEXT_VALID_CHANGED("0 0 1 \"text/plain\" Zm 9v", + "0 0 1 \"text/plain\" Zm9v"), + /* + * Valid, unquoted DOA-MEDIA-TYPE, non-empty DOA-DATA. + */ + TEXT_VALID_CHANGED("0 0 1 text/plain Zm9v", + "0 0 1 \"text/plain\" Zm9v"), + /* + * Invalid, quoted non-empty DOA-DATA. + */ + TEXT_INVALID("0 0 1 \"text/plain\" \"Zm9v\""), + /* + * Valid, empty DOA-DATA. + */ + TEXT_VALID("0 0 1 \"text/plain\" -"), + /* + * Invalid, quoted empty DOA-DATA. + */ + TEXT_INVALID("0 0 1 \"text/plain\" \"-\""), + /* + * Invalid, missing "-" in empty DOA-DATA. + */ + TEXT_INVALID("0 0 1 \"text/plain\""), + /* + * Valid, undefined DOA-LOCATION. + */ + TEXT_VALID("0 0 100 \"text/plain\" Zm9v"), + /* + * Invalid, DOA-LOCATION too big. + */ + TEXT_INVALID("0 0 256 \"text/plain\" ZM9v"), + /* + * Valid, empty DOA-MEDIA-TYPE, non-empty DOA-DATA. + */ + TEXT_VALID("0 0 2 \"\" aHR0cHM6Ly93d3cuaXNjLm9yZy8="), + /* + * Valid, empty DOA-MEDIA-TYPE, empty DOA-DATA. + */ + TEXT_VALID("0 0 1 \"\" -"), + /* + * Valid, DOA-MEDIA-TYPE with a space. + */ + TEXT_VALID("0 0 1 \"plain text\" Zm9v"), + /* + * Invalid, missing DOA-MEDIA-TYPE. + */ + TEXT_INVALID("1234567890 1234567890 1"), + /* + * Valid, DOA-DATA over 255 octets. + */ + TEXT_VALID("1234567890 1234567890 1 \"image/gif\" " + "R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM" + "/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAA" + "AAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c" + "3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS" + "1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeF" + "AgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9" + "pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1" + "SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7"), + /* + * Invalid, bad Base64 in DOA-DATA. + */ + TEXT_INVALID("1234567890 1234567890 1 \"image/gif\" R0lGODl"), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + wire_ok_t wire_ok[] = { + /* + * Valid, empty DOA-MEDIA-TYPE, empty DOA-DATA. + */ + WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + 0x01, 0x00), + /* + * Invalid, missing DOA-MEDIA-TYPE. + */ + WIRE_INVALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + 0x01), + /* + * Invalid, malformed DOA-MEDIA-TYPE length. + */ + WIRE_INVALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + 0x01, 0xff), + /* + * Valid, empty DOA-DATA. + */ + WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + 0x01, 0x03, 0x66, 0x6f, 0x6f), + /* + * Valid, non-empty DOA-DATA. + */ + WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + 0x01, 0x03, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72), + /* + * Valid, DOA-DATA over 255 octets. + */ + WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + 0x01, 0x06, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, + 0x00, 0x66, 0x99, 0xff, 0xff, 0xff, 0x33, 0x99, + 0xcc, 0xcc, 0xff, 0xff, 0x99, 0xcc, 0xff, 0x33, + 0x66, 0x99, 0x66, 0xcc, 0xff, 0x99, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x00, 0x99, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x21, 0xf9, 0x04, + 0x01, 0x0a, 0x00, 0x0f, 0x00, 0x2c, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x19, 0x00, 0x00, 0x04, + 0xc7, 0xf0, 0x81, 0x49, 0x2b, 0x95, 0x36, 0x6b, + 0x8d, 0xf7, 0xec, 0x5e, 0x68, 0x81, 0x19, 0x29, + 0x9e, 0x80, 0x89, 0xae, 0x5c, 0xbb, 0x3e, 0xb0, + 0x8a, 0xca, 0x1f, 0x1c, 0xdc, 0x78, 0x00, 0x87, + 0x34, 0xf7, 0xe4, 0xc0, 0xdb, 0x6e, 0xd3, 0xbb, + 0xfc, 0x82, 0x48, 0x1d, 0xb1, 0xa2, 0x3a, 0x26, + 0x93, 0xc5, 0x54, 0xe9, 0x49, 0x55, 0x96, 0x2e, + 0xa3, 0x6a, 0xd5, 0x45, 0x72, 0x6a, 0x93, 0x52, + 0xd7, 0x07, 0x77, 0x38, 0x0c, 0x6e, 0x83, 0x42, + 0xe1, 0x9c, 0x2b, 0x9b, 0x71, 0x58, 0x6c, 0xc7, + 0x2b, 0x10, 0x9c, 0xeb, 0x78, 0x01, 0x3a, 0x6f, + 0xbf, 0x31, 0xe5, 0x17, 0x39, 0x75, 0x03, 0x03, + 0x83, 0x85, 0x67, 0x85, 0x02, 0x04, 0x69, 0x7a, + 0x7e, 0x7f, 0x52, 0x18, 0x5e, 0x01, 0x83, 0x05, + 0x75, 0x40, 0x78, 0x48, 0x57, 0x29, 0x18, 0x41, + 0x86, 0x75, 0x07, 0x82, 0x02, 0xa0, 0x41, 0x2d, + 0x3b, 0x92, 0x93, 0x7d, 0x04, 0x79, 0x77, 0x7d, + 0xa4, 0x4b, 0x00, 0x6c, 0xa1, 0xb1, 0x8c, 0x7a, + 0x83, 0x48, 0x4d, 0x12, 0xa7, 0xa8, 0xb1, 0x37, + 0x83, 0x75, 0x04, 0x99, 0x9b, 0x73, 0xb9, 0x48, + 0x86, 0x6b, 0x01, 0x89, 0xc8, 0x75, 0x6b, 0x03, + 0xc0, 0x8e, 0x46, 0x35, 0x49, 0x94, 0x7c, 0x6c, + 0x95, 0xab, 0xcf, 0x7f, 0x36, 0x48, 0x6a, 0x88, + 0x05, 0x04, 0x05, 0x41, 0xde, 0x08, 0xb1, 0x44, + 0xda, 0x5f, 0xe7, 0x1e, 0xba, 0xe7, 0x4f, 0x11, + 0x00, 0x3b), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + UNUSED(tc); + + check_rdata(text_ok, wire_ok, false, dns_rdataclass_in, + dns_rdatatype_doa, sizeof(dns_rdata_doa_t)); +} + +/* + * EDNS Client Subnet tests. + * + * RFC 7871: + * + * 6. Option Format + * + * This protocol uses an EDNS0 [RFC6891] option to include client + * address information in DNS messages. The option is structured as + * follows: + * + * +0 (MSB) +1 (LSB) + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 0: | OPTION-CODE | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 2: | OPTION-LENGTH | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 4: | FAMILY | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 6: | SOURCE PREFIX-LENGTH | SCOPE PREFIX-LENGTH | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 8: | ADDRESS... / + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * o (Defined in [RFC6891]) OPTION-CODE, 2 octets, for ECS is 8 (0x00 + * 0x08). + * + * o (Defined in [RFC6891]) OPTION-LENGTH, 2 octets, contains the + * length of the payload (everything after OPTION-LENGTH) in octets. + * + * o FAMILY, 2 octets, indicates the family of the address contained in + * the option, using address family codes as assigned by IANA in + * Address Family Numbers [Address_Family_Numbers]. + * + * The format of the address part depends on the value of FAMILY. This + * document only defines the format for FAMILY 1 (IPv4) and FAMILY 2 + * (IPv6), which are as follows: + * + * o SOURCE PREFIX-LENGTH, an unsigned octet representing the leftmost + * number of significant bits of ADDRESS to be used for the lookup. + * In responses, it mirrors the same value as in the queries. + * + * o SCOPE PREFIX-LENGTH, an unsigned octet representing the leftmost + * number of significant bits of ADDRESS that the response covers. + * In queries, it MUST be set to 0. + * + * o ADDRESS, variable number of octets, contains either an IPv4 or + * IPv6 address, depending on FAMILY, which MUST be truncated to the + * number of bits indicated by the SOURCE PREFIX-LENGTH field, + * padding with 0 bits to pad to the end of the last octet needed. + * + * o A server receiving an ECS option that uses either too few or too + * many ADDRESS octets, or that has non-zero ADDRESS bits set beyond + * SOURCE PREFIX-LENGTH, SHOULD return FORMERR to reject the packet, + * as a signal to the software developer making the request to fix + * their implementation. + * + * All fields are in network byte order ("big-endian", per [RFC1700], + * Data Notation). + */ +ATF_TC(edns_client_subnet); +ATF_TC_HEAD(edns_client_subnet, tc) { + atf_tc_set_md_var(tc, "descr", + "OPT RDATA with EDNS Client Subnet manipulations"); +} +ATF_TC_BODY(edns_client_subnet, tc) { + wire_ok_t wire_ok[] = { + /* + * Option code with no content. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 0x00), + /* + * Option code family 0, source 0, scope 0. + */ + WIRE_VALID(0x00, 0x08, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00), + /* + * Option code family 1 (IPv4), source 0, scope 0. + */ + WIRE_VALID(0x00, 0x08, 0x00, 0x04, + 0x00, 0x01, 0x00, 0x00), + /* + * Option code family 2 (IPv6) , source 0, scope 0. + */ + WIRE_VALID(0x00, 0x08, 0x00, 0x04, + 0x00, 0x02, 0x00, 0x00), + /* + * Extra octet. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, + 0x00), + /* + * Source too long for IPv4. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 8, + 0x00, 0x01, 33, 0x00, + 0x00, 0x00, 0x00, 0x00), + /* + * Source too long for IPv6. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 20, + 0x00, 0x02, 129, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00), + /* + * Scope too long for IPv4. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 8, + 0x00, 0x01, 0x00, 33, + 0x00, 0x00, 0x00, 0x00), + /* + * Scope too long for IPv6. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 20, + 0x00, 0x02, 0x00, 129, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00), + /* + * When family=0, source and scope should be 0. + */ + WIRE_VALID(0x00, 0x08, 0x00, 4, + 0x00, 0x00, 0x00, 0x00), + /* + * When family=0, source and scope should be 0. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 5, + 0x00, 0x00, 0x01, 0x00, + 0x00), + /* + * When family=0, source and scope should be 0. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 5, + 0x00, 0x00, 0x00, 0x01, + 0x00), + /* + * Length too short for source IPv4. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 7, + 0x00, 0x01, 32, 0x00, + 0x00, 0x00, 0x00), + /* + * Length too short for source IPv6. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 19, + 0x00, 0x02, 128, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + UNUSED(tc); + + check_rdata(NULL, wire_ok, true, dns_rdataclass_in, + dns_rdatatype_opt, sizeof(dns_rdata_opt_t)); +} + +/* + * Successful load test. + */ +ATF_TC(hip); +ATF_TC_HEAD(hip, tc) { + atf_tc_set_md_var(tc, "descr", "that a oversized HIP record will " + "be rejected"); +} +ATF_TC_BODY(hip, tc) { + unsigned char hipwire[DNS_RDATA_MAXLENGTH] = { + 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x04, 0x41, 0x42, 0x43, 0x44, 0x00 }; + unsigned char buf[1024*1024]; + isc_buffer_t source, target; + dns_rdata_t rdata; + dns_decompress_t dctx; + isc_result_t result; + size_t i; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Fill the rest of input buffer with compression pointers. + */ + for (i = 12; i < sizeof(hipwire) - 2; i += 2) { + hipwire[i] = 0xc0; + hipwire[i+1] = 0x06; + } + + isc_buffer_init(&source, hipwire, sizeof(hipwire)); + isc_buffer_add(&source, sizeof(hipwire)); + isc_buffer_setactive(&source, i); + isc_buffer_init(&target, buf, sizeof(buf)); + dns_rdata_init(&rdata); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); + result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, + dns_rdatatype_hip, &source, &dctx, + 0, &target); + dns_decompress_invalidate(&dctx); + ATF_REQUIRE_EQ(result, DNS_R_FORMERR); + + dns_test_end(); +} + +/* + * ISDN tests. + * + * RFC 1183: + * + * 3.2. The ISDN RR + * + * The ISDN RR is defined with mnemonic ISDN and type code 20 (decimal). + * + * An ISDN (Integrated Service Digital Network) number is simply a + * telephone number. The intent of the members of the CCITT is to + * upgrade all telephone and data network service to a common service. + * + * The numbering plan (E.163/E.164) is the same as the familiar + * international plan for POTS (an un-official acronym, meaning Plain + * Old Telephone Service). In E.166, CCITT says "An E.163/E.164 + * telephony subscriber may become an ISDN subscriber without a number + * change." + * + * ISDN has the following format: + * + * <owner> <ttl> <class> ISDN <ISDN-address> <sa> + * + * The <ISDN-address> field is required; <sa> is optional. + * + * <ISDN-address> identifies the ISDN number of <owner> and DDI (Direct + * Dial In) if any, as defined by E.164 [8] and E.163 [7], the ISDN and + * PSTN (Public Switched Telephone Network) numbering plan. E.163 + * defines the country codes, and E.164 the form of the addresses. Its + * format in master files is a <character-string> syntactically + * identical to that used in TXT and HINFO. + * + * <sa> specifies the subaddress (SA). The format of <sa> in master + * files is a <character-string> syntactically identical to that used in + * TXT and HINFO. + * + * The format of ISDN is class insensitive. ISDN RRs cause no + * additional section processing. + * + * The <ISDN-address> is a string of characters, normally decimal + * digits, beginning with the E.163 country code and ending with the DDI + * if any. Note that ISDN, in Q.931, permits any IA5 character in the + * general case. + * + * The <sa> is a string of hexadecimal digits. For digits 0-9, the + * concrete encoding in the Q.931 call setup information element is + * identical to BCD. + * + * For example: + * + * Relay.Prime.COM. IN ISDN 150862028003217 + * sh.Prime.COM. IN ISDN 150862028003217 004 + * + * (Note: "1" is the country code for the North American Integrated + * Numbering Area, i.e., the system of "area codes" familiar to people + * in those countries.) + * + * The RR data is the ASCII representation of the digits. It is encoded + * as one or two <character-string>s, i.e., count followed by + * characters. + */ +ATF_TC(isdn); +ATF_TC_HEAD(isdn, tc) { + atf_tc_set_md_var(tc, "descr", "ISDN RDATA manipulations"); +} +ATF_TC_BODY(isdn, tc) { + wire_ok_t wire_ok[] = { + /* + * "". + */ + WIRE_VALID(0x00), + /* + * "\001". + */ + WIRE_VALID(0x01, 0x01), + /* + * "\001" "". + */ + WIRE_VALID(0x01, 0x01, 0x00), + /* + * "\001" "\001". + */ + WIRE_VALID(0x01, 0x01, 0x01, 0x01), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + UNUSED(tc); + + check_rdata(NULL, wire_ok, false, dns_rdataclass_in, + dns_rdatatype_isdn, sizeof(dns_rdata_isdn_t)); +} + +/* + * NSEC tests. + * + * RFC 4034: + * + * 4.1. NSEC RDATA Wire Format + * + * The RDATA of the NSEC RR is as shown below: + * + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * / Next Domain Name / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * / Type Bit Maps / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 4.1.1. The Next Domain Name Field + * + * The Next Domain field contains the next owner name (in the canonical + * ordering of the zone) that has authoritative data or contains a + * delegation point NS RRset; see Section 6.1 for an explanation of + * canonical ordering. The value of the Next Domain Name field in the + * last NSEC record in the zone is the name of the zone apex (the owner + * name of the zone's SOA RR). This indicates that the owner name of + * the NSEC RR is the last name in the canonical ordering of the zone. + * + * A sender MUST NOT use DNS name compression on the Next Domain Name + * field when transmitting an NSEC RR. + * + * Owner names of RRsets for which the given zone is not authoritative + * (such as glue records) MUST NOT be listed in the Next Domain Name + * unless at least one authoritative RRset exists at the same owner + * name. + * + * 4.1.2. The Type Bit Maps Field + * + * The Type Bit Maps field identifies the RRset types that exist at the + * NSEC RR's owner name. + * + * The RR type space is split into 256 window blocks, each representing + * the low-order 8 bits of the 16-bit RR type space. Each block that + * has at least one active RR type is encoded using a single octet + * window number (from 0 to 255), a single octet bitmap length (from 1 + * to 32) indicating the number of octets used for the window block's + * bitmap, and up to 32 octets (256 bits) of bitmap. + * + * Blocks are present in the NSEC RR RDATA in increasing numerical + * order. + * + * Type Bit Maps Field = ( Window Block # | Bitmap Length | Bitmap )+ + * + * where "|" denotes concatenation. + * + * Each bitmap encodes the low-order 8 bits of RR types within the + * window block, in network bit order. The first bit is bit 0. For + * window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds + * to RR type 2 (NS), and so forth. For window block 1, bit 1 + * corresponds to RR type 257, and bit 2 to RR type 258. If a bit is + * set, it indicates that an RRset of that type is present for the NSEC + * RR's owner name. If a bit is clear, it indicates that no RRset of + * that type is present for the NSEC RR's owner name. + * + * Bits representing pseudo-types MUST be clear, as they do not appear + * in zone data. If encountered, they MUST be ignored upon being read. + */ +ATF_TC(nsec); +ATF_TC_HEAD(nsec, tc) { + atf_tc_set_md_var(tc, "descr", "NSEC RDATA manipulations"); +} +ATF_TC_BODY(nsec, tc) { + text_ok_t text_ok[] = { + TEXT_INVALID(""), + TEXT_INVALID("."), + TEXT_VALID(". RRSIG"), + TEXT_SENTINEL() + }; + wire_ok_t wire_ok[] = { + WIRE_INVALID(0x00), + WIRE_INVALID(0x00, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00), + WIRE_VALID(0x00, 0x00, 0x01, 0x02), + WIRE_INVALID() + }; + + UNUSED(tc); + + check_rdata(text_ok, wire_ok, false, dns_rdataclass_in, + dns_rdatatype_nsec, sizeof(dns_rdata_nsec_t)); +} + +/* + * NSEC3 tests. + * + * RFC 5155. + */ +ATF_TC(nsec3); +ATF_TC_HEAD(nsec3, tc) { + atf_tc_set_md_var(tc, "descr", "NSEC3 RDATA manipulations"); +} +ATF_TC_BODY(nsec3, tc) { + text_ok_t text_ok[] = { + TEXT_INVALID(""), + TEXT_INVALID("."), + TEXT_INVALID(". RRSIG"), + TEXT_INVALID("1 0 10 76931F"), + TEXT_INVALID("1 0 10 76931F IMQ912BREQP1POLAH3RMONG;UED541AS"), + TEXT_INVALID("1 0 10 76931F IMQ912BREQP1POLAH3RMONG;UED541AS A RRSIG"), + TEXT_VALID("1 0 10 76931F AJHVGTICN6K0VDA53GCHFMT219SRRQLM A RRSIG"), + TEXT_VALID("1 0 10 76931F AJHVGTICN6K0VDA53GCHFMT219SRRQLM"), + TEXT_VALID("1 0 10 - AJHVGTICN6K0VDA53GCHFMT219SRRQLM"), + TEXT_SENTINEL() + }; + + UNUSED(tc); + + check_rdata(text_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_nsec3, sizeof(dns_rdata_nsec3_t)); +} + +/* + * WKS tests. + * + * RFC 1035: + * + * 3.4.2. WKS RDATA format + * + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ADDRESS | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | PROTOCOL | | + * +--+--+--+--+--+--+--+--+ | + * | | + * / <BIT MAP> / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * where: + * + * ADDRESS An 32 bit Internet address + * + * PROTOCOL An 8 bit IP protocol number + * + * <BIT MAP> A variable length bit map. The bit map must be a + * multiple of 8 bits long. + * + * The WKS record is used to describe the well known services supported by + * a particular protocol on a particular internet address. The PROTOCOL + * field specifies an IP protocol number, and the bit map has one bit per + * port of the specified protocol. The first bit corresponds to port 0, + * the second to port 1, etc. If the bit map does not include a bit for a + * protocol of interest, that bit is assumed zero. The appropriate values + * and mnemonics for ports and protocols are specified in [RFC-1010]. + * + * For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port + * 25 (SMTP). If this bit is set, a SMTP server should be listening on TCP + * port 25; if zero, SMTP service is not supported on the specified + * address. + */ +ATF_TC(wks); +ATF_TC_HEAD(wks, tc) { + atf_tc_set_md_var(tc, "descr", "WKS RDATA manipulations"); +} +ATF_TC_BODY(wks, tc) { + wire_ok_t wire_ok[] = { + /* + * Too short. + */ + WIRE_INVALID(0x00, 0x08, 0x00, 0x00), + /* + * Minimal TCP. + */ + WIRE_VALID(0x00, 0x08, 0x00, 0x00, 6), + /* + * Minimal UDP. + */ + WIRE_VALID(0x00, 0x08, 0x00, 0x00, 17), + /* + * Minimal other. + */ + WIRE_VALID(0x00, 0x08, 0x00, 0x00, 1), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + UNUSED(tc); + + check_rdata(NULL, wire_ok, false, dns_rdataclass_in, + dns_rdatatype_wks, sizeof(dns_rdata_in_wks_t)); +} + +/***** + ***** Main + *****/ + +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, csync); + ATF_TP_ADD_TC(tp, doa); + ATF_TP_ADD_TC(tp, edns_client_subnet); + ATF_TP_ADD_TC(tp, hip); + ATF_TP_ADD_TC(tp, isdn); + ATF_TP_ADD_TC(tp, nsec); + ATF_TP_ADD_TC(tp, nsec3); + ATF_TP_ADD_TC(tp, wks); + + return (atf_no_error()); +} diff --git a/lib/dns/tests/rdataset_test.c b/lib/dns/tests/rdataset_test.c new file mode 100644 index 0000000..b055846 --- /dev/null +++ b/lib/dns/tests/rdataset_test.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> + +#include <dns/rdataset.h> +#include <dns/rdatastruct.h> + +#include "dnstest.h" + + +/* + * Individual unit tests + */ + +/* Successful load test */ +ATF_TC(trimttl); +ATF_TC_HEAD(trimttl, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a " + "valid master file and returns success"); +} +ATF_TC_BODY(trimttl, tc) { + isc_result_t result; + dns_rdataset_t rdataset, sigrdataset; + dns_rdata_rrsig_t rrsig; + isc_stdtime_t ttltimenow, ttltimeexpire; + + ttltimenow = 10000000; + ttltimeexpire = ttltimenow + 800; + + UNUSED(tc); + + dns_rdataset_init(&rdataset); + dns_rdataset_init(&sigrdataset); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + rdataset.ttl = 900; + sigrdataset.ttl = 1000; + rrsig.timeexpire = ttltimeexpire; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, + true); + ATF_REQUIRE_EQ(rdataset.ttl, 800); + ATF_REQUIRE_EQ(sigrdataset.ttl, 800); + + rdataset.ttl = 900; + sigrdataset.ttl = 1000; + rrsig.timeexpire = ttltimenow - 200; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, + true); + ATF_REQUIRE_EQ(rdataset.ttl, 120); + ATF_REQUIRE_EQ(sigrdataset.ttl, 120); + + rdataset.ttl = 900; + sigrdataset.ttl = 1000; + rrsig.timeexpire = ttltimenow - 200; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, + false); + ATF_REQUIRE_EQ(rdataset.ttl, 0); + ATF_REQUIRE_EQ(sigrdataset.ttl, 0); + + sigrdataset.ttl = 900; + rdataset.ttl = 1000; + rrsig.timeexpire = ttltimeexpire; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, + true); + ATF_REQUIRE_EQ(rdataset.ttl, 800); + ATF_REQUIRE_EQ(sigrdataset.ttl, 800); + + sigrdataset.ttl = 900; + rdataset.ttl = 1000; + rrsig.timeexpire = ttltimenow - 200; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, + true); + ATF_REQUIRE_EQ(rdataset.ttl, 120); + ATF_REQUIRE_EQ(sigrdataset.ttl, 120); + + sigrdataset.ttl = 900; + rdataset.ttl = 1000; + rrsig.timeexpire = ttltimenow - 200; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, + false); + ATF_REQUIRE_EQ(rdataset.ttl, 0); + ATF_REQUIRE_EQ(sigrdataset.ttl, 0); + + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, trimttl); + + return (atf_no_error()); +} + diff --git a/lib/dns/tests/rdatasetstats_test.c b/lib/dns/tests/rdatasetstats_test.c new file mode 100644 index 0000000..0c2d5c5 --- /dev/null +++ b/lib/dns/tests/rdatasetstats_test.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <inttypes.h> +#include <stdbool.h> +#include <unistd.h> + +#include <isc/print.h> + +#include <dns/stats.h> + +#include "dnstest.h" + +/* + * Helper functions + */ +static void +set_typestats(dns_stats_t *stats, dns_rdatatype_t type, + bool stale) +{ + dns_rdatastatstype_t which; + unsigned int attributes; + + attributes = 0; + if (stale) attributes |= DNS_RDATASTATSTYPE_ATTR_STALE; + which = DNS_RDATASTATSTYPE_VALUE(type, attributes); + dns_rdatasetstats_increment(stats, which); + + attributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET; + if (stale) attributes |= DNS_RDATASTATSTYPE_ATTR_STALE; + which = DNS_RDATASTATSTYPE_VALUE(type, attributes); + dns_rdatasetstats_increment(stats, which); +} + +static void +set_nxdomainstats(dns_stats_t *stats, bool stale) { + dns_rdatastatstype_t which; + unsigned int attributes; + + attributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN; + if (stale) attributes |= DNS_RDATASTATSTYPE_ATTR_STALE; + which = DNS_RDATASTATSTYPE_VALUE(0, attributes); + dns_rdatasetstats_increment(stats, which); +} + +#define ATTRIBUTE_SET(y) ((attributes & (y)) != 0) +static void +checkit1(dns_rdatastatstype_t which, uint64_t value, void *arg) { + unsigned int attributes; +#if debug + unsigned int type; +#endif + + UNUSED(which); + UNUSED(arg); + + attributes = DNS_RDATASTATSTYPE_ATTR(which); +#if debug + type = DNS_RDATASTATSTYPE_BASE(which); + + fprintf(stderr, "%s%s%s%s/%u, %u\n", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) ? "O" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXRRSET) ? "!" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_STALE) ? "#" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) ? "X" : " ", + type, (unsigned)value); +#endif + if ((attributes & DNS_RDATASTATSTYPE_ATTR_STALE) == 0) + ATF_REQUIRE_EQ(value, 1); + else + ATF_REQUIRE_EQ(value, 0); +} + +static void +checkit2(dns_rdatastatstype_t which, uint64_t value, void *arg) { + unsigned int attributes; +#if debug + unsigned int type; +#endif + + UNUSED(which); + UNUSED(arg); + + attributes = DNS_RDATASTATSTYPE_ATTR(which); +#if debug + type = DNS_RDATASTATSTYPE_BASE(which); + + fprintf(stderr, "%s%s%s%s/%u, %u\n", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) ? "O" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXRRSET) ? "!" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_STALE) ? "#" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) ? "X" : " ", + type, (unsigned)value); +#endif + if ((attributes & DNS_RDATASTATSTYPE_ATTR_STALE) == 0) + ATF_REQUIRE_EQ(value, 0); + else + ATF_REQUIRE_EQ(value, 1); +} +/* + * Individual unit tests + */ + +ATF_TC(rdatasetstats); +ATF_TC_HEAD(rdatasetstats, tc) { + atf_tc_set_md_var(tc, "descr", "test that rdatasetstats counters are properly set"); +} +ATF_TC_BODY(rdatasetstats, tc) { + unsigned int i; + dns_stats_t *stats = NULL; + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_rdatasetstats_create(mctx, &stats); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* First 256 types. */ + for (i = 0; i <= 255; i++) + set_typestats(stats, (dns_rdatatype_t)i, false); + /* Specials */ + set_typestats(stats, dns_rdatatype_dlv, false); + set_typestats(stats, (dns_rdatatype_t)1000, false); + set_nxdomainstats(stats, false); + + /* + * Check that all counters are set to appropriately. + */ + dns_rdatasetstats_dump(stats, checkit1, NULL, 1); + + /* First 256 types. */ + for (i = 0; i <= 255; i++) + set_typestats(stats, (dns_rdatatype_t)i, true); + /* Specials */ + set_typestats(stats, dns_rdatatype_dlv, true); + set_typestats(stats, (dns_rdatatype_t)1000, true); + set_nxdomainstats(stats, true); + + /* + * Check that all counters are set to appropriately. + */ + dns_rdatasetstats_dump(stats, checkit2, NULL, 1); + + dns_stats_detach(&stats); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, rdatasetstats); + return (atf_no_error()); +} diff --git a/lib/dns/tests/resolver_test.c b/lib/dns/tests/resolver_test.c new file mode 100644 index 0000000..518622d --- /dev/null +++ b/lib/dns/tests/resolver_test.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> + +#include <isc/app.h> +#include <isc/buffer.h> +#include <isc/socket.h> +#include <isc/task.h> +#include <isc/timer.h> + +#include <dns/dispatch.h> +#include <dns/name.h> +#include <dns/resolver.h> +#include <dns/view.h> + +#include "dnstest.h" + +static dns_dispatchmgr_t *dispatchmgr = NULL; +static dns_dispatch_t *dispatch = NULL; +static dns_view_t *view = NULL; + + +static void +setup(void) { + isc_result_t result; + isc_sockaddr_t local; + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_makeview("view", &view); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_sockaddr_any(&local); + result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &local, + 4096, 100, 100, 100, 500, 0, 0, + &dispatch); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); +} + +static void +teardown(void) { + dns_dispatch_detach(&dispatch); + dns_view_detach(&view); + dns_dispatchmgr_destroy(&dispatchmgr); + dns_test_end(); +} + + +static void +mkres(dns_resolver_t **resolverp) { + isc_result_t result; + + result = dns_resolver_create(view, taskmgr, 1, 1, + socketmgr, timermgr, 0, + dispatchmgr, dispatch, NULL, resolverp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); +} + +static void +destroy_resolver(dns_resolver_t **resolverp) { + dns_resolver_shutdown(*resolverp); + dns_resolver_detach(resolverp); +} + +ATF_TC(create); +ATF_TC_HEAD(create, tc) { + atf_tc_set_md_var(tc, "descr", "dns_resolver_create"); +} +ATF_TC_BODY(create, tc) { + dns_resolver_t *resolver = NULL; + + UNUSED(tc); + + setup(); + mkres(&resolver); + destroy_resolver(&resolver); + teardown(); +} + +ATF_TC(gettimeout); +ATF_TC_HEAD(gettimeout, tc) { + atf_tc_set_md_var(tc, "descr", "dns_resolver_gettimeout"); +} +ATF_TC_BODY(gettimeout, tc) { + dns_resolver_t *resolver = NULL; + unsigned int timeout; + + UNUSED(tc); + + setup(); + mkres(&resolver); + + timeout = dns_resolver_gettimeout(resolver); + ATF_CHECK(timeout > 0); + + destroy_resolver(&resolver); + teardown(); +} + +ATF_TC(settimeout); +ATF_TC_HEAD(settimeout, tc) { + atf_tc_set_md_var(tc, "descr", "dns_resolver_settimeout"); +} +ATF_TC_BODY(settimeout, tc) { + dns_resolver_t *resolver = NULL; + unsigned int default_timeout, timeout; + + UNUSED(tc); + + setup(); + + mkres(&resolver); + + default_timeout = dns_resolver_gettimeout(resolver); + dns_resolver_settimeout(resolver, default_timeout + 1); + timeout = dns_resolver_gettimeout(resolver); + ATF_CHECK(timeout == default_timeout + 1); + + destroy_resolver(&resolver); + teardown(); +} + +ATF_TC(settimeout_default); +ATF_TC_HEAD(settimeout_default, tc) { + atf_tc_set_md_var(tc, "descr", "dns_resolver_settimeout to default"); +} +ATF_TC_BODY(settimeout_default, tc) { + dns_resolver_t *resolver = NULL; + unsigned int default_timeout, timeout; + + UNUSED(tc); + + setup(); + + mkres(&resolver); + + default_timeout = dns_resolver_gettimeout(resolver); + dns_resolver_settimeout(resolver, default_timeout + 10); + + timeout = dns_resolver_gettimeout(resolver); + ATF_CHECK_EQ(timeout, default_timeout + 10); + + dns_resolver_settimeout(resolver, 0); + timeout = dns_resolver_gettimeout(resolver); + ATF_CHECK_EQ(timeout, default_timeout); + + destroy_resolver(&resolver); + teardown(); +} + +ATF_TC(settimeout_belowmin); +ATF_TC_HEAD(settimeout_belowmin, tc) { + atf_tc_set_md_var(tc, "descr", + "dns_resolver_settimeout below minimum"); +} +ATF_TC_BODY(settimeout_belowmin, tc) { + dns_resolver_t *resolver = NULL; + unsigned int default_timeout, timeout; + + UNUSED(tc); + + setup(); + + mkres(&resolver); + + default_timeout = dns_resolver_gettimeout(resolver); + dns_resolver_settimeout(resolver, 9); + + timeout = dns_resolver_gettimeout(resolver); + ATF_CHECK_EQ(timeout, default_timeout); + + destroy_resolver(&resolver); + teardown(); +} + +ATF_TC(settimeout_overmax); +ATF_TC_HEAD(settimeout_overmax, tc) { + atf_tc_set_md_var(tc, "descr", "dns_resolver_settimeout over maximum"); +} +ATF_TC_BODY(settimeout_overmax, tc) { + dns_resolver_t *resolver = NULL; + unsigned int timeout; + + UNUSED(tc); + + setup(); + + mkres(&resolver); + + dns_resolver_settimeout(resolver, 4000000); + timeout = dns_resolver_gettimeout(resolver); + ATF_CHECK(timeout < 4000000 && timeout > 0); + + destroy_resolver(&resolver); + teardown(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, create); + ATF_TP_ADD_TC(tp, gettimeout); + ATF_TP_ADD_TC(tp, settimeout); + ATF_TP_ADD_TC(tp, settimeout_default); + ATF_TP_ADD_TC(tp, settimeout_belowmin); + ATF_TP_ADD_TC(tp, settimeout_overmax); + return (atf_no_error()); +} diff --git a/lib/dns/tests/rsa_test.c b/lib/dns/tests/rsa_test.c new file mode 100644 index 0000000..fb207ef --- /dev/null +++ b/lib/dns/tests/rsa_test.c @@ -0,0 +1,312 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* ! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdio.h> +#include <string.h> + +#include <isc/util.h> +#include <isc/print.h> + +#include <pk11/site.h> + +#include "dnstest.h" + +#include "../dst_internal.h" + +#if defined(OPENSSL) || defined(PKCS11CRYPTO) + +static unsigned char d[10] = { + 0xa, 0x10, 0xbb, 0, 0xfe, 0x15, 0x1, 0x88, 0xcc, 0x7d +}; + +static unsigned char sigsha1[256] = { + 0x45, 0x55, 0xd6, 0xf8, 0x05, 0xd2, 0x2e, 0x79, + 0x14, 0x2b, 0x1b, 0xd1, 0x4b, 0xb7, 0xcd, 0xc0, + 0xa2, 0xf3, 0x85, 0x32, 0x1f, 0xa3, 0xfd, 0x1f, + 0x30, 0xe0, 0xde, 0xb2, 0x6f, 0x3c, 0x8e, 0x2b, + 0x82, 0x92, 0xcd, 0x1c, 0x1b, 0xdf, 0xe6, 0xd5, + 0x4d, 0x93, 0xe6, 0xaa, 0x40, 0x28, 0x1b, 0x7b, + 0x2e, 0x40, 0x4d, 0xb5, 0x4d, 0x43, 0xe8, 0xfc, + 0x93, 0x86, 0x68, 0xe3, 0xbf, 0x73, 0x9a, 0x1e, + 0x6b, 0x5d, 0x52, 0xb8, 0x98, 0x1c, 0x94, 0xe1, + 0x85, 0x8b, 0xee, 0xb1, 0x4f, 0x22, 0x71, 0xcb, + 0xfd, 0xb2, 0xa8, 0x88, 0x64, 0xb4, 0xb1, 0x4a, + 0xa1, 0x7a, 0xce, 0x52, 0x83, 0xd8, 0xf2, 0x9e, + 0x67, 0x4c, 0xc3, 0x37, 0x74, 0xfe, 0xe0, 0x25, + 0x2a, 0xfd, 0xa3, 0x09, 0xff, 0x8a, 0x92, 0x0d, + 0xa9, 0xb3, 0x90, 0x23, 0xbe, 0x6a, 0x2c, 0x9e, + 0x5c, 0x6d, 0xb4, 0xa7, 0xd7, 0x97, 0xdd, 0xc6, + 0xb8, 0xae, 0xd4, 0x88, 0x64, 0x63, 0x1e, 0x85, + 0x20, 0x09, 0xea, 0xc4, 0x0b, 0xca, 0xbf, 0x83, + 0x5c, 0x89, 0xae, 0x64, 0x15, 0x76, 0x06, 0x51, + 0xb6, 0xa1, 0x99, 0xb2, 0x3c, 0x50, 0x99, 0x86, + 0x7d, 0xc7, 0xca, 0x4e, 0x1d, 0x2c, 0x17, 0xbb, + 0x6c, 0x7a, 0xc9, 0x3f, 0x5e, 0x28, 0x57, 0x2c, + 0xda, 0x01, 0x1d, 0xe8, 0x01, 0xf8, 0xf6, 0x37, + 0xe1, 0x34, 0x56, 0xae, 0x6e, 0xb1, 0xd4, 0xa2, + 0xc4, 0x02, 0xc1, 0xca, 0x96, 0xb0, 0x06, 0x72, + 0x2a, 0x27, 0xaa, 0xc8, 0xd5, 0x50, 0x81, 0x49, + 0x46, 0x33, 0xf8, 0xf7, 0x6b, 0xf4, 0x9c, 0x30, + 0x90, 0x50, 0xf6, 0x16, 0x76, 0x9d, 0xc6, 0x73, + 0xb5, 0xbc, 0x8a, 0xb6, 0x1d, 0x98, 0xcb, 0xce, + 0x36, 0x6f, 0x60, 0xec, 0x96, 0x49, 0x08, 0x85, + 0x5b, 0xc1, 0x8e, 0xb0, 0xea, 0x9e, 0x1f, 0xd6, + 0x27, 0x7f, 0xb6, 0xe0, 0x04, 0x12, 0xd2, 0x81 +}; + +#ifndef PK11_MD5_DISABLE +static unsigned char sigmd5[256] = { + 0xc0, 0x99, 0x90, 0xd6, 0xea, 0xc1, 0x5f, 0xc7, + 0x23, 0x60, 0xfc, 0x13, 0x3d, 0xcc, 0xda, 0x93, + 0x19, 0xf7, 0x22, 0xa9, 0x55, 0xbe, 0x70, 0x3c, + 0x87, 0x24, 0x8a, 0x7e, 0xa7, 0x59, 0x58, 0xd3, + 0x0e, 0x7c, 0x50, 0x3c, 0x81, 0x0f, 0x7a, 0x2b, + 0xb1, 0x94, 0x21, 0x87, 0xe4, 0x87, 0xcd, 0x2b, + 0xb9, 0xf1, 0xb8, 0x26, 0xc1, 0x02, 0xf4, 0x30, + 0x83, 0x41, 0x89, 0x61, 0xcc, 0x3d, 0xe3, 0x0f, + 0xec, 0x4a, 0x74, 0x95, 0x10, 0x65, 0xac, 0xd1, + 0xf5, 0x95, 0xe9, 0x99, 0xa8, 0x45, 0x98, 0x99, + 0xb5, 0xfd, 0x7a, 0x78, 0x80, 0xe5, 0x00, 0x33, + 0xa5, 0x54, 0xe5, 0xa3, 0xc0, 0x1b, 0x6c, 0xb9, + 0x77, 0x52, 0x6f, 0xe5, 0x85, 0xa8, 0xfa, 0x45, + 0x78, 0x49, 0x14, 0xa0, 0x10, 0x58, 0x40, 0x80, + 0x90, 0xc6, 0x55, 0x52, 0x6d, 0x46, 0x58, 0x50, + 0x3d, 0x5e, 0x40, 0x25, 0x51, 0x7c, 0xc4, 0x12, + 0x87, 0x2d, 0x7b, 0x10, 0xcd, 0x80, 0xec, 0x5d, + 0x27, 0x15, 0x09, 0x37, 0x1f, 0xa7, 0x86, 0x15, + 0xd1, 0xdd, 0xf1, 0x86, 0x1e, 0x42, 0x3a, 0xf9, + 0x5a, 0xed, 0x33, 0x07, 0xa9, 0x98, 0x08, 0x79, + 0xc5, 0xa4, 0x09, 0x95, 0x6e, 0x12, 0xfe, 0xee, + 0x49, 0x61, 0xe0, 0x99, 0xaa, 0x34, 0xa5, 0xca, + 0x82, 0xd3, 0x9b, 0x1c, 0x5b, 0x79, 0xf5, 0x0e, + 0x2c, 0x6c, 0x3b, 0x48, 0xd1, 0xbc, 0xd0, 0xda, + 0x73, 0xba, 0xe1, 0x81, 0x48, 0x27, 0x39, 0x2f, + 0x98, 0x77, 0x08, 0xb3, 0xf7, 0x38, 0x28, 0x6d, + 0x02, 0x56, 0xfa, 0x31, 0xbb, 0x14, 0x81, 0x6b, + 0x3c, 0x24, 0xa2, 0x68, 0x7a, 0x0a, 0x53, 0xbd, + 0x9d, 0x57, 0xd0, 0x99, 0x10, 0x28, 0x78, 0x69, + 0x31, 0x93, 0xa4, 0x73, 0x8d, 0x1a, 0xe4, 0xdc, + 0x0c, 0x15, 0xb8, 0x51, 0xd8, 0x66, 0x6a, 0x95, + 0x56, 0x17, 0x0a, 0x45, 0x72, 0xb5, 0xb8, 0xc4 +}; +#endif + +static unsigned char sigsha256[256] = { + 0x83, 0x53, 0x15, 0xfc, 0xca, 0xdb, 0xf6, 0x0d, + 0x53, 0x24, 0x5b, 0x5a, 0x8e, 0xd0, 0xbe, 0x5e, + 0xbc, 0xe8, 0x9e, 0x92, 0x3c, 0xfa, 0x93, 0x03, + 0xce, 0x2f, 0xc7, 0x6d, 0xd0, 0xbb, 0x9d, 0x06, + 0x83, 0xc6, 0xd3, 0xc0, 0xc1, 0x57, 0x9c, 0x82, + 0x17, 0x7f, 0xb5, 0xf8, 0x31, 0x18, 0xda, 0x46, + 0x05, 0x2c, 0xf8, 0xea, 0xaa, 0xcd, 0x99, 0x18, + 0xff, 0x23, 0x5e, 0xef, 0xf0, 0x87, 0x47, 0x6e, + 0x91, 0xfd, 0x19, 0x0b, 0x39, 0x19, 0x6a, 0xc8, + 0xdf, 0x71, 0x66, 0x8e, 0xa9, 0xa0, 0x79, 0x5c, + 0x2c, 0x52, 0x00, 0x61, 0x17, 0x86, 0x66, 0x03, + 0x52, 0xad, 0xec, 0x06, 0x53, 0xd9, 0x6d, 0xe3, + 0xe3, 0xea, 0x28, 0x15, 0xb3, 0x75, 0xf4, 0x61, + 0x7d, 0xed, 0x69, 0x2c, 0x24, 0xf3, 0x21, 0xb1, + 0x8a, 0xea, 0x60, 0xa2, 0x9e, 0x6a, 0xa6, 0x53, + 0x12, 0xf6, 0x5c, 0xef, 0xd7, 0x49, 0x4a, 0x02, + 0xe7, 0xf8, 0x64, 0x89, 0x13, 0xac, 0xd5, 0x1e, + 0x58, 0xff, 0xa1, 0x63, 0xdd, 0xa0, 0x1f, 0x44, + 0x99, 0x6a, 0x59, 0x7f, 0x35, 0xbd, 0xf1, 0xf3, + 0x7a, 0x28, 0x44, 0xe3, 0x4c, 0x68, 0xb1, 0xb3, + 0x97, 0x3c, 0x46, 0xe3, 0xc2, 0x12, 0x9e, 0x68, + 0x0b, 0xa6, 0x6c, 0x8f, 0x58, 0x48, 0x44, 0xa4, + 0xf7, 0xa7, 0xc2, 0x91, 0x8f, 0xbf, 0x00, 0xd0, + 0x01, 0x35, 0xd4, 0x86, 0x6e, 0x1f, 0xea, 0x42, + 0x60, 0xb1, 0x84, 0x27, 0xf4, 0x99, 0x36, 0x06, + 0x98, 0x12, 0x83, 0x32, 0x9f, 0xcd, 0x50, 0x5a, + 0x5e, 0xb8, 0x8e, 0xfe, 0x8d, 0x8d, 0x33, 0x2d, + 0x45, 0xe1, 0xc9, 0xdf, 0x2a, 0xd8, 0x38, 0x1d, + 0x95, 0xd4, 0x42, 0xee, 0x93, 0x5b, 0x0f, 0x1e, + 0x07, 0x06, 0x3a, 0x92, 0xf1, 0x59, 0x1d, 0x6e, + 0x1c, 0x31, 0xf3, 0xce, 0xa9, 0x1f, 0xad, 0x4d, + 0x76, 0x4d, 0x24, 0x98, 0xe2, 0x0e, 0x8c, 0x35 +}; + +static unsigned char sigsha512[512] = { + 0x4e, 0x2f, 0x63, 0x42, 0xc5, 0xf3, 0x05, 0x4a, + 0xa6, 0x3a, 0x93, 0xa0, 0xd9, 0x33, 0xa0, 0xd1, + 0x46, 0x33, 0x42, 0xe8, 0x74, 0xeb, 0x3b, 0x10, + 0x82, 0xd7, 0xcf, 0x39, 0x23, 0xb3, 0xe9, 0x23, + 0x53, 0x87, 0x8c, 0xee, 0x78, 0xcb, 0xb3, 0xd9, + 0xd2, 0x6d, 0x1a, 0x7c, 0x01, 0x4f, 0xed, 0x8d, + 0xf2, 0x72, 0xe4, 0x6a, 0x00, 0x8a, 0x60, 0xa6, + 0xd5, 0x9c, 0x43, 0x6c, 0xef, 0x38, 0x0c, 0x74, + 0x82, 0x5d, 0x22, 0xaa, 0x87, 0x81, 0x90, 0x9c, + 0x64, 0x07, 0x9b, 0x13, 0x51, 0xe0, 0xa5, 0xc2, + 0x83, 0x78, 0x2b, 0x9b, 0xb3, 0x8a, 0x9d, 0x36, + 0x33, 0xbd, 0x0d, 0x53, 0x84, 0xae, 0xe8, 0x13, + 0x36, 0xf6, 0xdf, 0x96, 0xe9, 0xda, 0xc3, 0xd7, + 0xa9, 0x2f, 0xf3, 0x5e, 0x5f, 0x1f, 0x7f, 0x38, + 0x7e, 0x8d, 0xbe, 0x90, 0x5e, 0x13, 0xb2, 0x20, + 0xbb, 0x9d, 0xfe, 0xe1, 0x52, 0xce, 0xe6, 0x80, + 0xa7, 0x95, 0x24, 0x59, 0xe3, 0xac, 0x24, 0xc4, + 0xfa, 0x1c, 0x44, 0x34, 0x29, 0x8d, 0xb1, 0xd0, + 0xd9, 0x4c, 0xff, 0xc4, 0xdb, 0xca, 0xc4, 0x3f, + 0x38, 0xf9, 0xe4, 0xaf, 0x75, 0x0a, 0x67, 0x4d, + 0xa0, 0x2b, 0xb0, 0x83, 0xce, 0x53, 0xc4, 0xb9, + 0x2e, 0x61, 0xb6, 0x64, 0xe5, 0xb5, 0xe5, 0xac, + 0x9d, 0x51, 0xec, 0x58, 0x42, 0x90, 0x78, 0xf6, + 0x46, 0x96, 0xef, 0xb6, 0x97, 0xb7, 0x54, 0x28, + 0x1a, 0x4c, 0x29, 0xf4, 0x7a, 0x33, 0xc6, 0x07, + 0xfd, 0xec, 0x97, 0x36, 0x1d, 0x42, 0x88, 0x94, + 0x27, 0xc2, 0xa3, 0xe1, 0xd4, 0x87, 0xa1, 0x8a, + 0x2b, 0xff, 0x47, 0x60, 0xfe, 0x1f, 0xaf, 0xc2, + 0xeb, 0x17, 0xdd, 0x56, 0xc5, 0x94, 0x5c, 0xcb, + 0x23, 0xe5, 0x49, 0x4d, 0x99, 0x06, 0x02, 0x5a, + 0xfc, 0xfc, 0xdc, 0xee, 0x49, 0xbc, 0x47, 0x60, + 0xff, 0x6a, 0x63, 0x8b, 0xe1, 0x2e, 0xa3, 0xa7 +}; + +ATF_TC(isc_rsa_verify); +ATF_TC_HEAD(isc_rsa_verify, tc) { + atf_tc_set_md_var(tc, "descr", "RSA verify"); +} +ATF_TC_BODY(isc_rsa_verify, tc) { + isc_result_t ret; + dns_fixedname_t fname; + isc_buffer_t buf; + dns_name_t *name; + dst_key_t *key = NULL; + dst_context_t *ctx = NULL; + isc_region_t r; + + UNUSED(tc); + + ret = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + name = dns_fixedname_initname(&fname); + isc_buffer_constinit(&buf, "rsa.", 4); + isc_buffer_add(&buf, 4); + ret = dns_name_fromtext(name, &buf, NULL, 0, NULL); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + ret = dst_key_fromfile(name, 29235, DST_ALG_RSASHA1, + DST_TYPE_PUBLIC, "./", mctx, &key); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + /* RSASHA1 */ + + ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_DNSSEC, + false, &ctx); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + r.base = d; + r.length = 10; + ret = dst_context_adddata(ctx, &r); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + r.base = sigsha1; + r.length = 256; + ret = dst_context_verify(ctx, &r); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + dst_context_destroy(&ctx); + + /* RSAMD5 */ + +#ifndef PK11_MD5_DISABLE + key->key_alg = DST_ALG_RSAMD5; + + ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_DNSSEC, + false, &ctx); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + r.base = d; + r.length = 10; + ret = dst_context_adddata(ctx, &r); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + r.base = sigmd5; + r.length = 256; + ret = dst_context_verify(ctx, &r); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + dst_context_destroy(&ctx); +#endif + + /* RSASHA256 */ + + key->key_alg = DST_ALG_RSASHA256; + + ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_DNSSEC, + false, &ctx); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + r.base = d; + r.length = 10; + ret = dst_context_adddata(ctx, &r); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + r.base = sigsha256; + r.length = 256; + ret = dst_context_verify(ctx, &r); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + dst_context_destroy(&ctx); + + /* RSASHA512 */ + + key->key_alg = DST_ALG_RSASHA512; + + ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_DNSSEC, + false, &ctx); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + r.base = d; + r.length = 10; + ret = dst_context_adddata(ctx, &r); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + r.base = sigsha512; + r.length = 256; + ret = dst_context_verify(ctx, &r); + ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + + dst_context_destroy(&ctx); + + + dst_key_free(&key); + dns_test_end(); +} +#else +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping RSA test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("RSA not available"); +} +#endif +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { +#if defined(OPENSSL) || defined(PKCS11CRYPTO) + ATF_TP_ADD_TC(tp, isc_rsa_verify); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + return (atf_no_error()); +} + diff --git a/lib/dns/tests/sigs_test.c b/lib/dns/tests/sigs_test.c new file mode 100644 index 0000000..20fd4b6 --- /dev/null +++ b/lib/dns/tests/sigs_test.c @@ -0,0 +1,479 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <isc/util.h> + +#if defined(OPENSSL) || defined(PKCS11CRYPTO) +#include <string.h> + +#include <dns/db.h> +#include <dns/diff.h> +#include <dns/dnssec.h> +#include <dns/fixedname.h> +#include <dns/name.h> +#include <dns/rdata.h> +#include <dns/rdatastruct.h> +#include <dns/rdatatype.h> +#include <dns/result.h> +#include <dns/types.h> +#include <dns/zone.h> + +#include <dst/dst.h> + +#include <isc/buffer.h> +#include <isc/list.h> +#include <isc/region.h> +#include <isc/stdtime.h> +#include <isc/result.h> +#include <isc/types.h> + +#include "../zone_p.h" + +#include "dnstest.h" + +/*% + * Structure characterizing a single diff tuple in the dns_diff_t structure + * prepared by dns__zone_updatesigs(). + */ +typedef struct { + dns_diffop_t op; + const char *owner; + dns_ttl_t ttl; + const char *type; +} zonediff_t; + +#define ZONEDIFF_SENTINEL { 0, NULL, 0, NULL } + +/*% + * Structure defining a dns__zone_updatesigs() test. + */ +typedef struct { + const char *description; /* test description */ + const zonechange_t *changes; /* array of "raw" zone changes */ + const zonediff_t *zonediff; /* array of "processed" zone changes */ +} updatesigs_test_params_t; + +/*% + * Check whether the 'found' tuple matches the 'expected' tuple. 'found' is + * the 'index'th tuple output by dns__zone_updatesigs() in test 'test'. + */ +static void +compare_tuples(const zonediff_t *expected, dns_difftuple_t *found, + const updatesigs_test_params_t *test, size_t index) +{ + char found_covers[DNS_RDATATYPE_FORMATSIZE] = { }; + char found_type[DNS_RDATATYPE_FORMATSIZE] = { }; + char found_name[DNS_NAME_FORMATSIZE]; + isc_consttextregion_t typeregion; + dns_fixedname_t expected_fname; + dns_rdatatype_t expected_type; + dns_name_t *expected_name; + dns_rdata_rrsig_t rrsig; + isc_buffer_t typebuf; + isc_result_t result; + + REQUIRE(expected != NULL); + REQUIRE(found != NULL); + REQUIRE(index > 0); + + /* + * Check operation. + */ + ATF_CHECK_EQ_MSG(expected->op, found->op, + "test \"%s\": tuple %zu: " + "expected op %d, found %d", + test->description, index, + expected->op, found->op); + + /* + * Check owner name. + */ + expected_name = dns_fixedname_initname(&expected_fname); + result = dns_name_fromstring(expected_name, expected->owner, 0, mctx); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_name_format(&found->name, found_name, sizeof(found_name)); + ATF_CHECK_MSG(dns_name_equal(expected_name, &found->name), + "test \"%s\": tuple %zu: " + "expected owner \"%s\", found \"%s\"", + test->description, index, + expected->owner, found_name); + + /* + * Check TTL. + */ + ATF_CHECK_EQ_MSG(expected->ttl, found->ttl, + "test \"%s\": tuple %zu: " + "expected TTL %u, found %u", + test->description, index, + expected->ttl, found->ttl); + + /* + * Parse expected RR type. + */ + typeregion.base = expected->type; + typeregion.length = strlen(expected->type); + result = dns_rdatatype_fromtext(&expected_type, + (isc_textregion_t*)&typeregion); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Format found RR type for reporting purposes. + */ + isc_buffer_init(&typebuf, found_type, sizeof(found_type)); + result = dns_rdatatype_totext(found->rdata.type, &typebuf); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Check RR type. + */ + switch (expected->op) { + case DNS_DIFFOP_ADDRESIGN: + case DNS_DIFFOP_DELRESIGN: + /* + * Found tuple must be of type RRSIG. + */ + ATF_CHECK_EQ_MSG(found->rdata.type, dns_rdatatype_rrsig, + "test \"%s\": tuple %zu: " + "expected type RRSIG, found %s", + test->description, index, + found_type); + if (found->rdata.type != dns_rdatatype_rrsig) { + break; + } + /* + * The signature must cover an RRset of type 'expected->type'. + */ + result = dns_rdata_tostruct(&found->rdata, &rrsig, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_buffer_init(&typebuf, found_covers, sizeof(found_covers)); + result = dns_rdatatype_totext(rrsig.covered, &typebuf); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ_MSG(expected_type, rrsig.covered, + "test \"%s\": tuple %zu: " + "expected RRSIG to cover %s, found covers %s", + test->description, index, + expected->type, found_covers); + break; + default: + /* + * Found tuple must be of type 'expected->type'. + */ + ATF_CHECK_EQ_MSG(expected_type, found->rdata.type, + "test \"%s\": tuple %zu: " + "expected type %s, found %s", + test->description, index, + expected->type, found_type); + break; + } +} + +/*% + * Perform a single dns__zone_updatesigs() test defined in 'test'. All other + * arguments are expected to remain constant between subsequent invocations of + * this function. + */ +static void +updatesigs_test(const updatesigs_test_params_t *test, dns_zone_t *zone, + dns_db_t *db, dst_key_t *zone_keys[], unsigned int nkeys, + isc_stdtime_t now) +{ + size_t tuples_expected, tuples_found, index; + dns_dbversion_t *version = NULL; + dns_diff_t raw_diff, zone_diff; + const zonediff_t *expected; + dns_difftuple_t *found; + isc_result_t result; + + dns__zonediff_t zonediff = { + .diff = &zone_diff, + .offline = false, + }; + + REQUIRE(test != NULL); + REQUIRE(test->description != NULL); + REQUIRE(test->changes != NULL); + REQUIRE(zone != NULL); + REQUIRE(db != NULL); + REQUIRE(zone_keys != NULL); + + /* + * Create a new version of the zone's database. + */ + result = dns_db_newversion(db, &version); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Create a diff representing the supplied changes. + */ + result = dns_test_difffromchanges(&raw_diff, test->changes); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Apply the "raw" diff to the new version of the zone's database as + * this is what dns__zone_updatesigs() expects to happen before it is + * called. + */ + dns_diff_apply(&raw_diff, db, version); + + /* + * Initialize the structure dns__zone_updatesigs() will modify. + */ + dns_diff_init(mctx, &zone_diff); + + /* + * Check whether dns__zone_updatesigs() behaves as expected. + */ + result = dns__zone_updatesigs(&raw_diff, db, version, zone_keys, nkeys, + zone, now - 3600, now + 3600, now, + true, false, &zonediff); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "test \"%s\": expected success, got %s", + test->description, isc_result_totext(result)); + ATF_CHECK_MSG(ISC_LIST_EMPTY(raw_diff.tuples), + "test \"%s\": raw diff was not emptied", + test->description); + ATF_CHECK_MSG(!ISC_LIST_EMPTY(zone_diff.tuples), + "test \"%s\": zone diff was not created", + test->description); + + /* + * Ensure that the number of tuples in the zone diff is as expected. + */ + + tuples_expected = 0; + for (expected = test->zonediff; + expected->owner != NULL; + expected++) + { + tuples_expected++; + } + + tuples_found = 0; + for (found = ISC_LIST_HEAD(zone_diff.tuples); + found != NULL; + found = ISC_LIST_NEXT(found, link)) + { + tuples_found++; + } + + ATF_REQUIRE_EQ_MSG(tuples_expected, tuples_found, + "test \"%s\": " + "expected %zu tuples in output, found %zu", + test->description, + tuples_expected, tuples_found); + + /* + * Ensure that every tuple in the zone diff matches expectations. + */ + expected = test->zonediff; + index = 1; + for (found = ISC_LIST_HEAD(zone_diff.tuples); + found != NULL; + found = ISC_LIST_NEXT(found, link)) + { + compare_tuples(expected, found, test, index); + expected++; + index++; + } + + /* + * Apply changes to zone database contents and clean up. + */ + dns_db_closeversion(db, &version, true); + dns_diff_clear(&zone_diff); + dns_diff_clear(&raw_diff); +} + +ATF_TC(updatesigs); +ATF_TC_HEAD(updatesigs, tc) { + atf_tc_set_md_var(tc, "descr", "dns__zone_updatesigs() tests"); +} +ATF_TC_BODY(updatesigs, tc) { + dst_key_t *zone_keys[DNS_MAXZONEKEYS]; + dns_zone_t *zone = NULL; + dns_db_t *db = NULL; + isc_result_t result; + unsigned int nkeys; + isc_stdtime_t now; + size_t i; + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Prepare a zone along with its signing keys. + */ + + result = dns_test_makezone("example", &zone, NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_zone, "example", + "testdata/master/master18.data"); + ATF_REQUIRE_EQ(result, DNS_R_SEENINCLUDE); + + result = dns_zone_setkeydirectory(zone, "testkeys"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_stdtime_get(&now); + result = dns__zone_findkeys(zone, db, NULL, now, mctx, DNS_MAXZONEKEYS, + zone_keys, &nkeys); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(nkeys, 2); + + /* + * Define the tests to be run. Note that changes to zone database + * contents introduced by each test are preserved between tests. + */ + + const zonechange_t changes_add[] = { + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo" }, + { DNS_DIFFOP_ADD, "bar.example", 600, "TXT", "bar" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_add[] = { + { DNS_DIFFOP_ADDRESIGN, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADDRESIGN, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_ADD, "bar.example", 600, "TXT" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_add = { + .description = "add new RRsets", + .changes = changes_add, + .zonediff = zonediff_add, + }; + + const zonechange_t changes_append[] = { + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo1" }, + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo2" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_append[] = { + { DNS_DIFFOP_DELRESIGN, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADDRESIGN, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_append = { + .description = "append multiple RRs to an existing RRset", + .changes = changes_append, + .zonediff = zonediff_append, + }; + + const zonechange_t changes_replace[] = { + { DNS_DIFFOP_DEL, "bar.example", 600, "TXT", "bar" }, + { DNS_DIFFOP_ADD, "bar.example", 600, "TXT", "rab" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_replace[] = { + { DNS_DIFFOP_DELRESIGN, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_ADDRESIGN, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_DEL, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_ADD, "bar.example", 600, "TXT" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_replace = { + .description = "replace an existing RRset", + .changes = changes_replace, + .zonediff = zonediff_replace, + }; + + const zonechange_t changes_delete[] = { + { DNS_DIFFOP_DEL, "bar.example", 600, "TXT", "rab" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_delete[] = { + { DNS_DIFFOP_DELRESIGN, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_DEL, "bar.example", 600, "TXT" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_delete = { + .description = "delete an existing RRset", + .changes = changes_delete, + .zonediff = zonediff_delete, + }; + + const zonechange_t changes_mixed[] = { + { DNS_DIFFOP_ADD, "baz.example", 900, "TXT", "baz1" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "A", "127.0.0.1" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "TXT", "baz2" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "AAAA", "::1" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_mixed[] = { + { DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "TXT" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "TXT" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "TXT" }, + { DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "A" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "A" }, + { DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "AAAA" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "AAAA" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_mixed = { + .description = "add different RRsets with common owner name", + .changes = changes_mixed, + .zonediff = zonediff_mixed, + }; + + const updatesigs_test_params_t *tests[] = { + &test_add, + &test_append, + &test_replace, + &test_delete, + &test_mixed, + }; + + /* + * Run tests. + */ + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + updatesigs_test(tests[i], zone, db, zone_keys, nkeys, now); + } + + /* + * Clean up. + */ + for (i = 0; i < nkeys; i++) { + dst_key_free(&zone_keys[i]); + } + dns_db_detach(&db); + dns_zone_detach(&zone); + + dns_test_end(); +} +#else +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping dns__zone_updatesigs() test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("DNSSEC support not compiled in"); +} +#endif + +ATF_TP_ADD_TCS(tp) { +#if defined(OPENSSL) || defined(PKCS11CRYPTO) + ATF_TP_ADD_TC(tp, updatesigs); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + + return (atf_no_error()); +} diff --git a/lib/dns/tests/testdata/db/data.db b/lib/dns/tests/testdata/db/data.db new file mode 100644 index 0000000..9ac043e --- /dev/null +++ b/lib/dns/tests/testdata/db/data.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum +a in ns ns.vix.com. +a in ns ns2.vix.com. +a in ns ns3.vix.com. +b in a 1.2.3.4 diff --git a/lib/dns/tests/testdata/dbiterator/zone1.data b/lib/dns/tests/testdata/dbiterator/zone1.data new file mode 100644 index 0000000..81c0abe --- /dev/null +++ b/lib/dns/tests/testdata/dbiterator/zone1.data @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ in soa localhost. postmaster.localhost. ( + 2011080901 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 600 ) ;minimum + in ns ns + in ns ns2 +ns in a 10.0.0.1 +ns2 in a 10.0.0.2 + +a in txt "test" +b in txt "test" +c in txt "test" +d.e.f in txt "test" +e in txt "test" +f.g.h in txt "test" +f.g.i in txt "test" +f.g.j in txt "test" +k in txt "test" diff --git a/lib/dns/tests/testdata/dbiterator/zone2.data b/lib/dns/tests/testdata/dbiterator/zone2.data new file mode 100644 index 0000000..7265c27 --- /dev/null +++ b/lib/dns/tests/testdata/dbiterator/zone2.data @@ -0,0 +1,319 @@ +; File written on Mon Aug 15 16:51:56 2011 +; dnssec_signzone version 9.7.3rc1 +test. 600 IN SOA localhost. postmaster.localhost. ( + 2011080901 ; serial + 3600 ; refresh (1 hour) + 1800 ; retry (30 minutes) + 604800 ; expire (1 week) + 600 ; minimum (10 minutes) + ) + 600 RRSIG SOA 7 1 600 20110914225156 ( + 20110815225156 39833 test. + IoQPcpx+Y2btVBBdM2H/9ppRMjphB1thwrdh + midhKH+MXDAauUIENucugi3zLsc1o2ke8LnQ + v3lCLd/bb5MD1otuS8vOw1GWEFhXOUBZU6wS + QwEIcG4BiSlz7/GvOlRa2znkOmZ3c8bD/J3Y + XUWDI3BEDPgrZqfxEvoMyPEWjO8= ) + 600 NS ns.test. + 600 NS ns2.test. + 600 RRSIG NS 7 1 600 20110914225156 ( + 20110815225156 39833 test. + OgEimhmFIAqlH0hyQy3pTsveBHKyqs9WfO1S + uDPRj3DFgFEAjoY473T8GxG2C+jTVL/UMVcb + BTZ8wIAiUHhqKLcmr0q/1X+kNUs7tNi+6oMn + /jxaOuRL6c8Kf2gl2t4g6JTwQqLQhUHTfQP+ + bEfKUr75VsVfxCQZIHlZ3/AlxZM= ) + 600 DNSKEY 256 3 7 ( + AwEAAc0FzrE7jUiaKIGZpIaFE8E989topAJN + dWIQUQ7BSKabmpBP2M+SXHwIiQ/yC25iqudO + IxjRcK7nHB1VoP84xU2oMj6eeSqQHf/bYaji + Y8IfR7lgrzoDWzq+0rtnKMJc/JM8SMkcoBAS + llvxarDJTZheZjlrCvhpRJC+FAkBsx81 + ) ; key id = 39833 + 600 DNSKEY 257 3 7 ( + AwEAAc55LPDhBLqfDUpjYYbBt+N63CiZtKrD + UDGeFAerbw0MWIUi3PgMr7yGVrj8e5Qjp9UN + zBUax6NdhlYVtFA8CwMTXGBjxgyqUoWpce08 + lswxfE70BpgUA6w5efs0/mYtX9/A76etCaSI + oNH2vfa47BCdCPDfC1uTgyeuNuDvhszHaSiD + 8OY7tLa/voecUlq38sdqi2raf2DvgOm7rdFa + reXOS/WIj7zd4XYrV1JGthxOMVlQ7zdv9rVd + UNUIF2d4hwCZJQr0ejhmvB3m/DuNmNOPYmnv + KTmLSE+IJ6baqYvKOVxwV+SaCnuJEjv+3Yrx + 8WQYD/iS9WBhC9FUit0dy+0= + ) ; key id = 57183 + 600 RRSIG DNSKEY 7 1 600 20110914225156 ( + 20110815225156 39833 test. + xPV+bSGUlbxA5MKBeeRbwUDh3Qc+dm77+OHQ + BHIr1L8/kRP5o5J7MqPA37kea6nhyltYf9xM + RsxyiaBGUUeLyWg/q6hTtkNgAHifOPAhiDz8 + AJDSTdSsq9RVtjdobAD0jyzz9sWnB+TPSOmj + Nlyd7VtPVEuSYljgawwfBBO3Kho= ) + 600 RRSIG DNSKEY 7 1 600 20110914225156 ( + 20110815225156 57183 test. + S3jkC7AvyFc4ShfHt6AWgS4zpx9DzWHBK9gV + 2H23OJzy8H1At/CjKxWVHLJ/io+ygryVnt/I + 47Jyhh9i43TnXj8il475YsweGnXGZSorrcXA + 3IsD2lOuRYnp3yetxe2ZrMGNDqqImE6X4x1a + UJI0cbE2UMZfUt8Rm5USiGzwAEgFD1OXxvMD + UT3flyp+Ote9FConK8gewV4wlJuBFemWT7BZ + lUYnoqfuAeEn2+1pIBS0iA0LNFjNBaEgtcjo + QeweN32yKoApau47Dl/Klw7KFT8+PLZ0QPbt + XAkJU7q94Q5aucDuHCSCTCc+2vZxdEnXKvRY + rfLuG8r/V5Kn+1iYrQ== ) + 0 NSEC3PARAM 1 0 10 - + 0 RRSIG NSEC3PARAM 7 1 0 20110914225156 ( + 20110815225156 39833 test. + kghSSeP8AZiQ/zmxgxAyG0itoUMo5adG5pxD + p8T3ZmbxEUSyG5acxBFkmeY39wVU0Cda8tWc + HHrMbB5e2GN8z6xJ0A4rVyXfKSYJSz+iKWfk + 7sOFRjd8OLYE3di6PwIpk6ORUiRPMFLDQCH0 + Q27hLsSoKyd50orKKI+ncjz7WzU= ) +a.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + UEVOlnL6CDRNCfk/Xge2oaGYCV1+ewwi5zJ0 + CX4DdwiNEkItL4HgBe8xXfxgFC3qySdsSYPE + 1krdFyIkAclMCwHECd1UwZbGlMTEUGrE1KOB + 8vQY+OhIV9TAhqNwnjbu7s2ZdNUv3wiUPcfk + hCJ4rzP6yeV2inLwZulXnhxb6Pk= ) +b.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + HcyQlO9io6Rc5e4vVqlRmK5PacOaFQJmdERG + 5Aobpgm1FuCLC7F+IMZ0d1XvBWnsw9iDzV43 + UKzTGqUSmDiSBzs4QzHlacGickIW8EOV4xyJ + +mcJ0FZh4YNbkt6CiX+8SF6IxfCMhRMjpSsK + rWqJMG3LXkI6W9stShzsYAFBOzQ= ) +e.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + jUn5FGRTL9OcFU7tvfkUnSwY8jA+8JynE0hi + ZJbYXDU5CiWGmR2B3yPHxUCewRqouyVCV8bc + xZsSuBxvcdYKryYDbjsmB83GlSEuxE9J7XZs + 8SxUP8PobLVqzXgEZS/XRU2G+R915ZDP9/iL + z9oYwc9TkeyXbp8J/ZsH88tG980= ) +c.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + cRxAj45oFDDCd8xQXxD1F0Qq8XeBWAj8EYS3 + 7nFXAgAy8sTczFvYCNGj79o7BALJwM4vc/wx + 6rjsiO/sHgfTMEBDq6lH9Wql72uhwavI2SrL + /h/wBP5q4BXlQ4xp6cLhhdifOWhNTvLP+Fe5 + U6yjvqneiKspze9SiFbcmRDiJds= ) +d.e.f.test. 600 IN TXT "test" + 600 RRSIG TXT 7 4 600 20110914225156 ( + 20110815225156 39833 test. + ENjCzr/P9rJmj5OJLzYwWtHtBg2Uz+qJDucz + I97Pq9F819/c5sxNfT4hgICCw6ZfT4ffbzye + fFJ0JVrh2cYOzu68ozlgek/Uml1UW0pDQVdI + s4zEgp4XK9wXUxtWChSqp5YXMdeHegZFu32i + IMNTbJDudwYSwhr2FyG92ZRi8Y8= ) +f.g.h.test. 600 IN TXT "test" + 600 RRSIG TXT 7 4 600 20110914225156 ( + 20110815225156 39833 test. + HT7iocFsfDjeX6j9RJdE3xfVGkIxhajFHgM/ + T/mJj/al4HKV6Ajia8DhpdfDrgM2m7r+Pgcn + FSIstfebQsuFCnHX/gIalDND/grHKsetQnMP + Y7O4QLsRnTV53fdlqQ4eT+jBW6fzJdGySVN+ + bg6kNJZS8DebjmlKtZz7tXjkP+4= ) +f.g.i.test. 600 IN TXT "test" + 600 RRSIG TXT 7 4 600 20110914225156 ( + 20110815225156 39833 test. + kHJJeNSL1rz4QRYqOzhGMQl1yIdio7l8Lg8H + f0TsvFLa6BudVtwKUm+Kz2QiDn7/Lew8w0KX + vVHxX/Vwl3Ixk54YgMKLNogz2TEvnh/VGiS7 + 8r0oSUrg0CFd+xDfxnLeRqX5NNfMuSJap5WH + Aw7IVeRjXDwJFYnytMEnTrhHHHg= ) +f.g.j.test. 600 IN TXT "test" + 600 RRSIG TXT 7 4 600 20110914225156 ( + 20110815225156 39833 test. + lIEHEhDFhOWK8W/F2xWELU2p/X77S2KTivm9 + sY4k3RPsLNHE7p+lF8p72Lcb79rtltnoVYtE + pTIiaUcmgGwfaI4cwfXbeuEgnuTiLg7Xrefx + 3GT86Q+8gfgbMXUmRA/eouWZhCOaYJN99gYz + urzDMiRLYmILHmLlnvo82SgXeuk= ) +k.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + wC3zgYWsuLga8Vu3QFu/Ci8SzRbA5bvjSmDj + NzcpjU5cvJBxtgzatCr02AaUC94bI0JzNrEB + nFyWCYw55lyy+bAHU1u05UcQmz0n5yxkvmHX + i8ZjMyQkAvNKodJHaFQqUKKIDuSHD2EziKqg + eNn55YRS11ihkODehUVNl7TnYeA= ) +ns.test. 600 IN A 10.0.0.1 + 600 RRSIG A 7 2 600 20110914225156 ( + 20110815225156 39833 test. + VyK/WlQ6ikXdjF/arGzyAyYhOc8IYNBp4QLW + gtYjvbjIcV5+9JINWmUs61VjJ14nES1sI0xb + 9vQJuiPXTM1awUAnvOKLhaX6fbJaEiR1w6Cf + RT5QKBMxNBKVStqdabHcigY4DUuc1PQk1vCw + yMUJt3nHNVMZk+XAycNHzBeYjik= ) +ns2.test. 600 IN A 10.0.0.2 + 600 RRSIG A 7 2 600 20110914225156 ( + 20110815225156 39833 test. + CX6UlZL+5NQJViKfbe/E3uIJk/wjUzoiHBhY + B6gS8nxZzlRPdTTXyMZoRa4etTZEbrRjnyXk + 1rP47faCUwbh//XqukN9f7FZ4Y39NpPS2XpX + 0Lx6M93Jz46lbzmseMFs2YmNMzzhN4uhRvl/ + 8gPtYsn9KMXnAlFfa4XrE5LNVyY= ) +1F3JQ6EANHNHOCMUPQTVNM339VDTR51C.test. 600 IN NSEC3 1 0 10 - 7QKPELF33JOK9BVJ7CKE99AHG40B0SH7 A RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + w7aS12lxLNh+G1B/2kEq1BO6IzYvyC8n/MGV + 0jvFnapNXGZMPrPxGeO2wkw1JXepuXCv98be + M4SjQywaH+VP6ZMTIfjxRxtcCM+aLAFhiz0l + /MILEkjemmxjAfvV7emRVMwCGcoGI7qC3Xxq + q5g8EzJiYyTCOnI5LKRggn97wGg= ) +7QKPELF33JOK9BVJ7CKE99AHG40B0SH7.test. 600 IN NSEC3 1 0 10 - 94Q15K1V1VE5F87EI37T2B9A39EEC368 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + J4ObL3p4eN0jWh06M+rX2SSPANQoKfnosElB + KcKE7fLqEjKK7N6Yh6KUlbEP25tfeZ7W6GBJ + b7q6Nh0Ax8fYdc/6JVvmxcwWcx5Lw1TfITGB + ttFntJlbp1A8lwP3pn8Ksql1X2ogh78AsgTb + X5kmXVukC1oEzt98EAa/V/an8QA= ) +CS8M3UVG0UJDR6USBES4U9SNUGQI2RJE.test. 600 IN NSEC3 1 0 10 - ETEQB5V431INUIIE547FKSOF7O4DJ62J A RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + Vyd/2b0S15fACJ8TiPXKtScV9A/ZztVumZAm + o2S6jaVJKWik+8orDW+WiJ4/PEl26PK2m1uv + HD2beuUCHj9EnYkN/dzL3Bsc302qr9xqsh0q + VFS2moznoNG415ZV3vgYR7L9DAp43ZeFuw6I + 7sr21hLYLUeo31xBsJg7RlOL+4s= ) +ETEQB5V431INUIIE547FKSOF7O4DJ62J.test. 600 IN NSEC3 1 0 10 - F8G1MB0JUEU3FBI11CAVFIPGEA3POOIM + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + oOHs1eb3JYeOMOnzE2PS6NIXBNzSoTYPIxo/ + P0d/ihsLKra3yNJNPTlu4kf+FZoNYAGtMK/D + 6dZWFvtdswDdi2C5WSgsanuHqXq5Lr3A1nCe + cQI5PO4RrLymB+MtYg15CNKcnc0WmJO8deSR + WzNOarC+Iz1Xj3FkKDS4FFr+02Q= ) +94Q15K1V1VE5F87EI37T2B9A39EEC368.test. 600 IN NSEC3 1 0 10 - CS8M3UVG0UJDR6USBES4U9SNUGQI2RJE + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + K0PvN7YtHQ63x/x2yXXa2S9GBGuTNJywDZ8M + wyMSwytCb9mn4hnKD5mJHaXGTw3YX7usbnEO + ce6hiJdN/VhMfbRMOvUpgyblOj4kXiYVZY1a + SyycfugK/Hu1j4az7lIhhnnx58GChA6mg8Vx + 3Uz6cNDDCSTBTl09NyeUUrKWsHQ= ) +FBH6B0LHT9PPQB1P98D228HA1H52L8PO.test. 600 IN NSEC3 1 0 10 - JGU2L7C3LKLHAKC5RHUOORTI2DCKK3KL + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + giXRE+4ZeIzDrhx1XkFSpIKGFd3UGzlrLZnO + Ur9nMUfwvU5A3fitEkdayo3ZDH7MQGpSotaH + ReiFXx3Z6Hm2NIN/RHYZQr9e0vbMYSjkANdu + HWBA1SrSq5SHyuy970mPd4jfTHiABCo6fJGB + ykGClZGou0WSaB+Ak19fMbeQ2Wo= ) +JGU2L7C3LKLHAKC5RHUOORTI2DCKK3KL.test. 600 IN NSEC3 1 0 10 - KFMJ88CKMKUQQJE59IKFBOLLLD4DF55H TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + BHTDUgZdWNLgz3xHYMqvlWK/IJ0xrXESoREc + 6D3sO9bcLTMYPO9t80itOlipwp4AmaVOBXPt + cKSdgsUXDEtHqNSxtGbNr5xQ+Aqsep0GX71V + HkcIuiNdTUw83dkajCHMkmQCbEjp9mbdiTmS + haNW2EsscldfaS1aq5tYUhCT3l4= ) +L993U6VC0DUV5QJ8TRPD2IQLM8FJ7AT9.test. 600 IN NSEC3 1 0 10 - LSMRLLNBQGGK8J6V40KLM2LG5TE4FS0P + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + vE7K0Nrju4qLFDYkIyMY5bIMT0wu8MJdxL6u + 7WVA4HepccKQcUnvVoBAcrA9+MUeteyrad8Y + SJvQIt7sz5t7FViWSq5IMPVPujWtW5J30LhJ + mOLd1KmnFWoVthJ1oFNzBM80A60seKNnEw1M + lV6Y+v0gNYIQensUb9w6SVMTpxE= ) +F8G1MB0JUEU3FBI11CAVFIPGEA3POOIM.test. 600 IN NSEC3 1 0 10 - FA1T7MKUUV9SD4VDBJQ3GRFK1IDTCKL7 + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + DkL9ONc0vpsKdG20ol8XPAaVfLb7kf1wnKbR + rQUB1trGSHm/Igo06of43zm9J+56htFJg1xD + I2de0sCUBQYyHVBBDiBAd1g+ZvcpUlLP0w8M + NxMviMiG/WQAdGXHwYfUimwMWD7gNGl1m05H + HwYmzGs+d1bClDNBrFhdfdL2+iA= ) +LSMRLLNBQGGK8J6V40KLM2LG5TE4FS0P.test. 600 IN NSEC3 1 0 10 - LUAN2Q3I2OCVSD41MP08HNA9JP22D38K + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + ZgiWuMqodQuhwuAF6CIiJTsdRahi+poOiZAM + WXNP0wXfdptcG2uhbdDwy+0crhe3tuybhwcb + CuiaQUh0XNPhgF+qmXpGobaqBhCEvCF4K9qY + OCIoMfsI1pIBVbMw0+YXVarFZ8+mfNU/+6n6 + yy2+1nCg3k4XR2Dpv4CeDBfcAuM= ) +NAL1UIEBM38NKMN6RQOKE8T781IA7UKI.test. 600 IN NSEC3 1 0 10 - OUSGP0LO9FGAROHDULQVSTI3OLQIBB39 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + x8JiXPI+EXHz8ZO/VW0/+9wWsBNqeSMxXZIV + ibOnogSg7Wi7Yq1xftKC2+xEevNxSZnBibEy + Sgro5xKTf0n7pD9hHVBLoYmOOnbXY3QNQ2EQ + y3LdPT355WmwVddVOOxNpNRp2zQyqg7BhVA3 + wxY7tyVQd4x1+95ATUQBnFditdE= ) +KFMJ88CKMKUQQJE59IKFBOLLLD4DF55H.test. 600 IN NSEC3 1 0 10 - L993U6VC0DUV5QJ8TRPD2IQLM8FJ7AT9 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + KQPaN2Ecebifbl4Bz5Yo0x2DgGmZiVhpSydm + oy/5NtMjt7G472JrKlqByap+VxW0bpzo3IER + 3P8Dsv7pfBD4/Cl5sFqwZL7wYy7RB4dQLVCi + Pepc/Mr3gR2XmL91fpGttMj5jGscnVQJCyFa + obzhsVaVImUQZFDPb0UQUHwIhOA= ) +LUAN2Q3I2OCVSD41MP08HNA9JP22D38K.test. 600 IN NSEC3 1 0 10 - NAL1UIEBM38NKMN6RQOKE8T781IA7UKI TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + NJ+X3d0qh2+fbSnG0iQPxAeDIOzX5NTmY9fS + x7IO/DDcgUhPvl1YYdz5J999cec1zzOKp10J + YbsIAzg0w/Y4D4CBUw3IkcOrUFOODb6eJQGb + rVFRqmp3BUP4qOAWUZvx4oQ0KG4K/h/KJMbU + Vcdl7PF7G5O5hMyR9UWg4zal7Sk= ) +OUSGP0LO9FGAROHDULQVSTI3OLQIBB39.test. 600 IN NSEC3 1 0 10 - PQQ28M3U2MM08GGFV3JKR76G2H9IUJPC TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + A/qxYrSE/smBGbST8j8eGPCrRnwvVa25kDha + IuA3nv0vzXhFvlruc9f0HRGwsq6A2pw3I5W+ + xo2/JxsNyFOotdwaDDEBzqPkJmrzupxQS4Hm + rHSLnRnNw4QzvzNjAGWMYAoe3OeHC47wmAtI + qE91EHZTlPP28CUXOMo+7sCaOa8= ) +U0UVS2SUP89P2TM3PJO4TC1GPJ2O6519.test. 600 IN NSEC3 1 0 10 - VA2VG5BEMCKQP6MS5NHHGL18031BIA7M NS SOA RRSIG DNSKEY NSEC3PARAM + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + rahhkfiF+Rk6oqbWTdu9qcwhmj5hbDuIFdiJ + GmaG+cFSv5Mjp+txNVCvBK9Hq/VpW0ypen/3 + JC0sVAugSX+HAKAgyaMKmgWCvoQZ6ZSJUh7o + LRPcT+oxVXQAqjovxpaV8k6sYo44tpljPdOD + UluWAP5SrmJKjzCxs27KGRx8MK4= ) +VA2VG5BEMCKQP6MS5NHHGL18031BIA7M.test. 600 IN NSEC3 1 0 10 - VAKOQ2TPD7S25NFBJT73J3C4OGU10RJ5 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + XcBeZ8lo9Qo8z56+1FdGDjh6ZHCfO+MQ/wnY + TEUo/aWLkPTyq39nLhe0qVBJxmDpM+KQFuG9 + cjQT5fvrlrY+lv6dedB64EBMYy4kKbIv7N5+ + r6+sfWlvtKsfXxysLSk2+jLEm5NuLFrOdNas + WLVsq741D3YcWt4kM1HCyk3DNF8= ) +FA1T7MKUUV9SD4VDBJQ3GRFK1IDTCKL7.test. 600 IN NSEC3 1 0 10 - FBH6B0LHT9PPQB1P98D228HA1H52L8PO TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + jB/vLrvx4sQQD7J3ZacAAyhcFmIPh7LH3ljw + IAIaeLb10oX5q1/nQKYdfq976TMy5sWpBcmd + i91WLxd+T/gOSumyP8bC3g+SUoyZ9wxY6A6a + MMx1rn0QA9IKrxMqojs9M3urJ8QAeIS+KyAn + rbyyJuG+EVm0prqlPZtzUi28WCI= ) +PQQ28M3U2MM08GGFV3JKR76G2H9IUJPC.test. 600 IN NSEC3 1 0 10 - U0UVS2SUP89P2TM3PJO4TC1GPJ2O6519 + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + asCOU9OkVWMvUU2IUpwMgdYf0faA04zPbaFf + qywYsv3NH01Lky6G3a0WUPAbBm7TAYx/ln8a + 559vlpp/gpXEl9CcLrjO6wy5i0ryp8gVHtKJ + rQlEc/uw4SY+S5t7FuZc2rNRdAbxVMYuwrvm + HBsKDPblre3e06ZZFEmnGFzCgmg= ) +VAKOQ2TPD7S25NFBJT73J3C4OGU10RJ5.test. 600 IN NSEC3 1 0 10 - VNCCJH8JPOLGLAGVMV3FKS09M7RRDU47 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + Pt4tKB1p/jsyLYab9LSt5MF1KTRT18nRTOox + q0IACkXkKx7W5xv6nSYXIB+nQzNp1Y1hhoXn + 9IFi0liPnIAOp73w4vybhfIdTFiEmHPHT6O9 + VIx5cSriqBI6Qda8GtfeIb96P8SojbUk5BDI + g18iYjviGhQYRgpU3tg1qd7pbcc= ) +VNCCJH8JPOLGLAGVMV3FKS09M7RRDU47.test. 600 IN NSEC3 1 0 10 - 1F3JQ6EANHNHOCMUPQTVNM339VDTR51C + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + ZMZPHawhkuzSV7C7zkgghH/jpw9CQVR1JUXq + pAeY2iIIWwNhfuskJaLgtu/5SuKnJtrv6D4N + g+lfEkBReia5xO/SCcHv8/hXEPH8vZ4xe1C9 + 6GVB6ip2hKw2g5HpyF7X18WgwZ0cqPWVg+Q+ + xRLpXH+53391Wt5rG7qJswn5RLE= ) diff --git a/lib/dns/tests/testdata/diff/zone1.data b/lib/dns/tests/testdata/diff/zone1.data new file mode 100644 index 0000000..6eb87ab --- /dev/null +++ b/lib/dns/tests/testdata/diff/zone1.data @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 +remove 0 A 5.6.7.8 diff --git a/lib/dns/tests/testdata/diff/zone2.data b/lib/dns/tests/testdata/diff/zone2.data new file mode 100644 index 0000000..d57d586 --- /dev/null +++ b/lib/dns/tests/testdata/diff/zone2.data @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 +remove 0 A 5.6.7.8 +added 0 A 5.6.7.8 diff --git a/lib/dns/tests/testdata/diff/zone3.data b/lib/dns/tests/testdata/diff/zone3.data new file mode 100644 index 0000000..65f12dd --- /dev/null +++ b/lib/dns/tests/testdata/diff/zone3.data @@ -0,0 +1,12 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 diff --git a/lib/dns/tests/testdata/dnstap/dnstap.saved b/lib/dns/tests/testdata/dnstap/dnstap.saved Binary files differnew file mode 100644 index 0000000..c657f41 --- /dev/null +++ b/lib/dns/tests/testdata/dnstap/dnstap.saved diff --git a/lib/dns/tests/testdata/dnstap/dnstap.text b/lib/dns/tests/testdata/dnstap/dnstap.text new file mode 100644 index 0000000..71977e4 --- /dev/null +++ b/lib/dns/tests/testdata/dnstap/dnstap.text @@ -0,0 +1,96 @@ +03-Feb-2017 15:47:16.000 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 SR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 SR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 SR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 SR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 CR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 CR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 CR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 CR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 AR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 AR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 AR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 AR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 RR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 RR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 RR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 RR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 FR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 FR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 FR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 FR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 TR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 TR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 TR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 TR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A diff --git a/lib/dns/tests/testdata/dnstap/query.auth b/lib/dns/tests/testdata/dnstap/query.auth new file mode 100644 index 0000000..a14f850 --- /dev/null +++ b/lib/dns/tests/testdata/dnstap/query.auth @@ -0,0 +1,4 @@ +# authoritative query, www.isc.org/A +8d 24 00 20 00 01 00 00 00 00 00 01 03 77 77 77 +03 69 73 63 03 6f 72 67 00 00 01 00 01 00 00 29 +10 00 00 00 00 00 00 00 diff --git a/lib/dns/tests/testdata/dnstap/query.recursive b/lib/dns/tests/testdata/dnstap/query.recursive new file mode 100644 index 0000000..8ee705f --- /dev/null +++ b/lib/dns/tests/testdata/dnstap/query.recursive @@ -0,0 +1,4 @@ +# recursive query for www.isc.org/A +bf 08 01 20 00 01 00 00 00 00 00 01 03 77 77 77 +03 69 73 63 03 6f 72 67 00 00 01 00 01 00 00 29 +10 00 00 00 00 00 00 00 diff --git a/lib/dns/tests/testdata/dnstap/response.auth b/lib/dns/tests/testdata/dnstap/response.auth new file mode 100644 index 0000000..4d0ea81 --- /dev/null +++ b/lib/dns/tests/testdata/dnstap/response.auth @@ -0,0 +1,19 @@ +# authoritative response, www.isc.org/A +8d 24 84 00 00 01 00 01 00 04 00 07 03 77 77 77 +03 69 73 63 03 6f 72 67 00 00 01 00 01 c0 0c 00 +01 00 01 00 00 00 3c 00 04 95 14 40 45 c0 10 00 +02 00 01 00 00 1c 20 00 0d 03 61 6d 73 06 73 6e +73 2d 70 62 c0 10 c0 10 00 02 00 01 00 00 1c 20 +00 07 04 73 66 62 61 c0 3d c0 10 00 02 00 01 00 +00 1c 20 00 19 02 6e 73 03 69 73 63 0b 61 66 69 +6c 69 61 73 2d 6e 73 74 04 69 6e 66 6f 00 c0 10 +00 02 00 01 00 00 1c 20 00 06 03 6f 72 64 c0 3d +c0 39 00 01 00 01 00 00 1c 20 00 04 c7 06 01 1e +c0 39 00 1c 00 01 00 00 1c 20 00 10 20 01 05 00 +00 60 00 00 00 00 00 00 00 00 00 30 c0 8a 00 01 +00 01 00 00 1c 20 00 04 c7 06 00 1e c0 8a 00 1c +00 01 00 00 1c 20 00 10 20 01 05 00 00 71 00 00 +00 00 00 00 00 00 00 30 c0 52 00 01 00 01 00 00 +1c 20 00 04 95 14 40 03 c0 52 00 1c 00 01 00 00 +1c 20 00 10 20 01 04 f8 00 00 00 02 00 00 00 00 +00 00 00 19 00 00 29 10 00 00 00 00 00 00 00 diff --git a/lib/dns/tests/testdata/dnstap/response.recursive b/lib/dns/tests/testdata/dnstap/response.recursive new file mode 100644 index 0000000..6e3a3cf --- /dev/null +++ b/lib/dns/tests/testdata/dnstap/response.recursive @@ -0,0 +1,19 @@ +# recursive response, www.isc.org/A +bf 08 81 a0 00 01 00 01 00 04 00 07 03 77 77 77 +03 69 73 63 03 6f 72 67 00 00 01 00 01 c0 0c 00 +01 00 01 00 00 00 15 00 04 95 14 40 45 c0 10 00 +02 00 01 00 00 1b a6 00 0e 04 73 66 62 61 06 73 +6e 73 2d 70 62 c0 10 c0 10 00 02 00 01 00 00 1b +a6 00 06 03 6f 72 64 c0 3e c0 10 00 02 00 01 00 +00 1b a6 00 19 02 6e 73 03 69 73 63 0b 61 66 69 +6c 69 61 73 2d 6e 73 74 04 69 6e 66 6f 00 c0 10 +00 02 00 01 00 00 1b a6 00 06 03 61 6d 73 c0 3e +c0 8a 00 01 00 01 00 00 b1 d5 00 04 c7 06 01 1e +c0 8a 00 1c 00 01 00 00 b1 d5 00 10 20 01 05 00 +00 60 00 00 00 00 00 00 00 00 00 30 c0 53 00 01 +00 01 00 00 b1 d5 00 04 c7 06 00 1e c0 53 00 1c +00 01 00 00 b1 d5 00 10 20 01 05 00 00 71 00 00 +00 00 00 00 00 00 00 30 c0 39 00 01 00 01 00 00 +b1 d5 00 04 95 14 40 03 c0 39 00 1c 00 01 00 00 +b1 d5 00 10 20 01 04 f8 00 00 00 02 00 00 00 00 +00 00 00 19 00 00 29 10 00 00 00 00 00 00 00 diff --git a/lib/dns/tests/testdata/dst/Ktest.+001+00002.key b/lib/dns/tests/testdata/dst/Ktest.+001+00002.key new file mode 100644 index 0000000..a8b4b4d --- /dev/null +++ b/lib/dns/tests/testdata/dst/Ktest.+001+00002.key @@ -0,0 +1 @@ +test. IN DNSKEY 49152 2 1 diff --git a/lib/dns/tests/testdata/dst/Ktest.+001+54622.key b/lib/dns/tests/testdata/dst/Ktest.+001+54622.key new file mode 100644 index 0000000..b0277e3 --- /dev/null +++ b/lib/dns/tests/testdata/dst/Ktest.+001+54622.key @@ -0,0 +1 @@ +test. IN DNSKEY 257 3 1 AQPQjwSpaVzxIgRCpiUoozUQKGh2oX8NIFKDOvtxK+tn536OZg2cROKTlgGEHXJK9YHfW/6nzQULTVpb63P+SQMmjCCidb8IYyhItixRztVeJQ== diff --git a/lib/dns/tests/testdata/dst/Ktest.+001+54622.private b/lib/dns/tests/testdata/dst/Ktest.+001+54622.private new file mode 100644 index 0000000..c97ac30 --- /dev/null +++ b/lib/dns/tests/testdata/dst/Ktest.+001+54622.private @@ -0,0 +1,10 @@ +Private-key-format: v1.2 +Algorithm: 1 (RSA) +Modulus: 0I8EqWlc8SIEQqYlKKM1EChodqF/DSBSgzr7cSvrZ+d+jmYNnETik5YBhB1ySvWB31v+p80FC01aW+tz/kkDJowgonW/CGMoSLYsUc7VXiU= +PublicExponent: Aw== +PrivateExponent: iwoDG5uTS2wC1xluGxd4tXBFpGuqCMA3AidSS3Kc7++ptEQJEtiXC9kfCJMvZhGfQLaujft2OgrmkcuDVtPIbQWEENhyJhb4Lk82kFXbfus= +Prime1: /rSKuzcZY7R5cY2YWD4CiBNyj9WJMq1wWmBnb9+5M08nTl5E9NW5qQ== +Prime2: 0Z5shXQYd16E2Gs6e5WxtO0Oqlly2KkSqXohwTQWDWTb8Pw0WTZmHQ== +Exponent1: qc2x0iS7l82mS7O65X6sWrehtTkGIcj1kZWaSpUmIjTE3umDTePRGw== +Exponent2: i77zA6K6+j8DOvIm/Q52eJ4JxuZMkHC3G6bBK3gOs5iSoKgi5iREEw== +Coefficient: 3+wYZB0SJad7z2EsjzgbSlg6CawoaOvrROGSbwSiW5DCsMFROudOTw== diff --git a/lib/dns/tests/testdata/dst/Ktest.+003+23616.key b/lib/dns/tests/testdata/dst/Ktest.+003+23616.key new file mode 100644 index 0000000..958d585 --- /dev/null +++ b/lib/dns/tests/testdata/dst/Ktest.+003+23616.key @@ -0,0 +1 @@ +test. IN DNSKEY 16641 3 3 ANp1//lqDlEfTavcFI+cyudNfgEz73V/K7fSDvkA0eDYcGg/kSvEjAEO/oLWCERltkuC55ZcM/mSv17WF1d/wR6kww/pLI9eXwkjftAYqs5sNxk+mbEGl6zwve9wq5z7IoTY5/J4l7XLCKftg/wGvrzXQhggIkRvEh3myhxd+ouILcpfvTIthWlTKiH59tSJpmgmiSMTE7nDYaf10iVRWN6DMSprgejiH05/fpmyZAt44tyAh4m1wXS5u4tam1PXDJYJozn7EfQ8e2weIv1yC+t6PHSx diff --git a/lib/dns/tests/testdata/dst/Ktest.+003+23616.private b/lib/dns/tests/testdata/dst/Ktest.+003+23616.private new file mode 100644 index 0000000..5781c9d --- /dev/null +++ b/lib/dns/tests/testdata/dst/Ktest.+003+23616.private @@ -0,0 +1,7 @@ +Private-key-format: v1.2 +Algorithm: 3 (DSA) +Prime(p): 73V/K7fSDvkA0eDYcGg/kSvEjAEO/oLWCERltkuC55ZcM/mSv17WF1d/wR6kww/pLI9eXwkjftAYqs5sNxk+mQ== +Subprime(q): 2nX/+WoOUR9Nq9wUj5zK501+ATM= +Base(g): sQaXrPC973CrnPsihNjn8niXtcsIp+2D/Aa+vNdCGCAiRG8SHebKHF36i4gtyl+9Mi2FaVMqIfn21ImmaCaJIw== +Private_value(x): Nky4tvIwg6xlcyeHXr4k2DEZg0E= +Public_value(y): ExO5w2Gn9dIlUVjegzEqa4Ho4h9Of36ZsmQLeOLcgIeJtcF0ubuLWptT1wyWCaM5+xH0PHtsHiL9cgvrejx0sQ== diff --git a/lib/dns/tests/testdata/dst/Ktest.+003+49667.key b/lib/dns/tests/testdata/dst/Ktest.+003+49667.key new file mode 100644 index 0000000..fb73f57 --- /dev/null +++ b/lib/dns/tests/testdata/dst/Ktest.+003+49667.key @@ -0,0 +1 @@ +test. IN DNSKEY 49152 2 3 diff --git a/lib/dns/tests/testdata/dst/test1.data b/lib/dns/tests/testdata/dst/test1.data new file mode 100644 index 0000000..b1a9bf5 --- /dev/null +++ b/lib/dns/tests/testdata/dst/test1.data @@ -0,0 +1,3077 @@ +Network Working Group P. Mockapetris +Request for Comments: 1035 ISI + November 1987 +Obsoletes: RFCs 882, 883, 973 + + DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION + + +1. STATUS OF THIS MEMO + +This RFC describes the details of the domain system and protocol, and +assumes that the reader is familiar with the concepts discussed in a +companion RFC, "Domain Names - Concepts and Facilities" [RFC-1034]. + +The domain system is a mixture of functions and data types which are an +official protocol and functions and data types which are still +experimental. Since the domain system is intentionally extensible, new +data types and experimental behavior should always be expected in parts +of the system beyond the official protocol. The official protocol parts +include standard queries, responses and the Internet class RR data +formats (e.g., host addresses). Since the previous RFC set, several +definitions have changed, so some previous definitions are obsolete. + +Experimental or obsolete features are clearly marked in these RFCs, and +such information should be used with caution. + +The reader is especially cautioned not to depend on the values which +appear in examples to be current or complete, since their purpose is +primarily pedagogical. Distribution of this memo is unlimited. + + Table of Contents + + 1. STATUS OF THIS MEMO 1 + 2. INTRODUCTION 3 + 2.1. Overview 3 + 2.2. Common configurations 4 + 2.3. Conventions 7 + 2.3.1. Preferred name syntax 7 + 2.3.2. Data Transmission Order 8 + 2.3.3. Character Case 9 + 2.3.4. Size limits 10 + 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10 + 3.1. Name space definitions 10 + 3.2. RR definitions 11 + 3.2.1. Format 11 + 3.2.2. TYPE values 12 + 3.2.3. QTYPE values 12 + 3.2.4. CLASS values 13 + + + +Mockapetris [Page 1] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 3.2.5. QCLASS values 13 + 3.3. Standard RRs 13 + 3.3.1. CNAME RDATA format 14 + 3.3.2. HINFO RDATA format 14 + 3.3.3. MB RDATA format (EXPERIMENTAL) 14 + 3.3.4. MD RDATA format (Obsolete) 15 + 3.3.5. MF RDATA format (Obsolete) 15 + 3.3.6. MG RDATA format (EXPERIMENTAL) 16 + 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16 + 3.3.8. MR RDATA format (EXPERIMENTAL) 17 + 3.3.9. MX RDATA format 17 + 3.3.10. NULL RDATA format (EXPERIMENTAL) 17 + 3.3.11. NS RDATA format 18 + 3.3.12. PTR RDATA format 18 + 3.3.13. SOA RDATA format 19 + 3.3.14. TXT RDATA format 20 + 3.4. ARPA Internet specific RRs 20 + 3.4.1. A RDATA format 20 + 3.4.2. WKS RDATA format 21 + 3.5. IN-ADDR.ARPA domain 22 + 3.6. Defining new types, classes, and special namespaces 24 + 4. MESSAGES 25 + 4.1. Format 25 + 4.1.1. Header section format 26 + 4.1.2. Question section format 28 + 4.1.3. Resource record format 29 + 4.1.4. Message compression 30 + 4.2. Transport 32 + 4.2.1. UDP usage 32 + 4.2.2. TCP usage 32 + 5. MASTER FILES 33 + 5.1. Format 33 + 5.2. Use of master files to define zones 35 + 5.3. Master file example 36 + 6. NAME SERVER IMPLEMENTATION 37 + 6.1. Architecture 37 + 6.1.1. Control 37 + 6.1.2. Database 37 + 6.1.3. Time 39 + 6.2. Standard query processing 39 + 6.3. Zone refresh and reload processing 39 + 6.4. Inverse queries (Optional) 40 + 6.4.1. The contents of inverse queries and responses 40 + 6.4.2. Inverse query and response example 41 + 6.4.3. Inverse query processing 42 + + + + + + +Mockapetris [Page 2] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 6.5. Completion queries and responses 42 + 7. RESOLVER IMPLEMENTATION 43 + 7.1. Transforming a user request into a query 43 + 7.2. Sending the queries 44 + 7.3. Processing responses 46 + 7.4. Using the cache 47 + 8. MAIL SUPPORT 47 + 8.1. Mail exchange binding 48 + 8.2. Mailbox binding (Experimental) 48 + 9. REFERENCES and BIBLIOGRAPHY 50 + Index 54 + +2. INTRODUCTION + +2.1. Overview + +The goal of domain names is to provide a mechanism for naming resources +in such a way that the names are usable in different hosts, networks, +protocol families, internets, and administrative organizations. + +From the user's point of view, domain names are useful as arguments to a +local agent, called a resolver, which retrieves information associated +with the domain name. Thus a user might ask for the host address or +mail information associated with a particular domain name. To enable +the user to request a particular type of information, an appropriate +query type is passed to the resolver with the domain name. To the user, +the domain tree is a single information space; the resolver is +responsible for hiding the distribution of data among name servers from +the user. + +From the resolver's point of view, the database that makes up the domain +space is distributed among various name servers. Different parts of the +domain space are stored in different name servers, although a particular +data item will be stored redundantly in two or more name servers. The +resolver starts with knowledge of at least one name server. When the +resolver processes a user query it asks a known name server for the +information; in return, the resolver either receives the desired +information or a referral to another name server. Using these +referrals, resolvers learn the identities and contents of other name +servers. Resolvers are responsible for dealing with the distribution of +the domain space and dealing with the effects of name server failure by +consulting redundant databases in other servers. + +Name servers manage two kinds of data. The first kind of data held in +sets called zones; each zone is the complete database for a particular +"pruned" subtree of the domain space. This data is called +authoritative. A name server periodically checks to make sure that its +zones are up to date, and if not, obtains a new copy of updated zones + + + +Mockapetris [Page 3] + +RFC 1035 Domain Implementation and Specification November 1987 + + +from master files stored locally or in another name server. The second +kind of data is cached data which was acquired by a local resolver. +This data may be incomplete, but improves the performance of the +retrieval process when non-local data is repeatedly accessed. Cached +data is eventually discarded by a timeout mechanism. + +This functional structure isolates the problems of user interface, +failure recovery, and distribution in the resolvers and isolates the +database update and refresh problems in the name servers. + +2.2. Common configurations + +A host can participate in the domain name system in a number of ways, +depending on whether the host runs programs that retrieve information +from the domain system, name servers that answer queries from other +hosts, or various combinations of both functions. The simplest, and +perhaps most typical, configuration is shown below: + + Local Host | Foreign + | + +---------+ +----------+ | +--------+ + | | user queries | |queries | | | + | User |-------------->| |---------|->|Foreign | + | Program | | Resolver | | | Name | + | |<--------------| |<--------|--| Server | + | | user responses| |responses| | | + +---------+ +----------+ | +--------+ + | A | + cache additions | | references | + V | | + +----------+ | + | cache | | + +----------+ | + +User programs interact with the domain name space through resolvers; the +format of user queries and user responses is specific to the host and +its operating system. User queries will typically be operating system +calls, and the resolver and its cache will be part of the host operating +system. Less capable hosts may choose to implement the resolver as a +subroutine to be linked in with every program that needs its services. +Resolvers answer user queries with information they acquire via queries +to foreign name servers and the local cache. + +Note that the resolver may have to make several queries to several +different foreign name servers to answer a particular user query, and +hence the resolution of a user query may involve several network +accesses and an arbitrary amount of time. The queries to foreign name +servers and the corresponding responses have a standard format described + + + +Mockapetris [Page 4] + +RFC 1035 Domain Implementation and Specification November 1987 + + +in this memo, and may be datagrams. + +Depending on its capabilities, a name server could be a stand alone +program on a dedicated machine or a process or processes on a large +timeshared host. A simple configuration might be: + + Local Host | Foreign + | + +---------+ | + / /| | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + +Here a primary name server acquires information about one or more zones +by reading master files from its local file system, and answers queries +about those zones that arrive from foreign resolvers. + +The DNS requires that all zones be redundantly supported by more than +one name server. Designated secondary servers can acquire zones and +check for updates from the primary server using the zone transfer +protocol of the DNS. This configuration is shown below: + + Local Host | Foreign + | + +---------+ | + / /| | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + A |maintenance | +--------+ + | +------------|->| | + | queries | |Foreign | + | | | Name | + +------------------|--| Server | + maintenance responses | +--------+ + +In this configuration, the name server periodically establishes a +virtual circuit to a foreign name server to acquire a copy of a zone or +to check that an existing copy has not changed. The messages sent for + + + +Mockapetris [Page 5] + +RFC 1035 Domain Implementation and Specification November 1987 + + +these maintenance activities follow the same form as queries and +responses, but the message sequences are somewhat different. + +The information flow in a host that supports all aspects of the domain +name system is shown below: + + Local Host | Foreign + | + +---------+ +----------+ | +--------+ + | | user queries | |queries | | | + | User |-------------->| |---------|->|Foreign | + | Program | | Resolver | | | Name | + | |<--------------| |<--------|--| Server | + | | user responses| |responses| | | + +---------+ +----------+ | +--------+ + | A | + cache additions | | references | + V | | + +----------+ | + | Shared | | + | database | | + +----------+ | + A | | + +---------+ refreshes | | references | + / /| | V | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + A |maintenance | +--------+ + | +------------|->| | + | queries | |Foreign | + | | | Name | + +------------------|--| Server | + maintenance responses | +--------+ + +The shared database holds domain space data for the local name server +and resolver. The contents of the shared database will typically be a +mixture of authoritative data maintained by the periodic refresh +operations of the name server and cached data from previous resolver +requests. The structure of the domain data and the necessity for +synchronization between name servers and resolvers imply the general +characteristics of this database, but the actual format is up to the +local implementor. + + + + +Mockapetris [Page 6] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Information flow can also be tailored so that a group of hosts act +together to optimize activities. Sometimes this is done to offload less +capable hosts so that they do not have to implement a full resolver. +This can be appropriate for PCs or hosts which want to minimize the +amount of new network code which is required. This scheme can also +allow a group of hosts can share a small number of caches rather than +maintaining a large number of separate caches, on the premise that the +centralized caches will have a higher hit ratio. In either case, +resolvers are replaced with stub resolvers which act as front ends to +resolvers located in a recursive server in one or more name servers +known to perform that service: + + Local Hosts | Foreign + | + +---------+ | + | | responses | + | Stub |<--------------------+ | + | Resolver| | | + | |----------------+ | | + +---------+ recursive | | | + queries | | | + V | | + +---------+ recursive +----------+ | +--------+ + | | queries | |queries | | | + | Stub |-------------->| Recursive|---------|->|Foreign | + | Resolver| | Server | | | Name | + | |<--------------| |<--------|--| Server | + +---------+ responses | |responses| | | + +----------+ | +--------+ + | Central | | + | cache | | + +----------+ | + +In any case, note that domain components are always replicated for +reliability whenever possible. + +2.3. Conventions + +The domain system has several conventions dealing with low-level, but +fundamental, issues. While the implementor is free to violate these +conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in +ALL behavior observed from other hosts. + +2.3.1. Preferred name syntax + +The DNS specifications attempt to be as general as possible in the rules +for constructing domain names. The idea is that the name of any +existing object can be expressed as a domain name with minimal changes. + + + +Mockapetris [Page 7] + +RFC 1035 Domain Implementation and Specification November 1987 + + +However, when assigning a domain name for an object, the prudent user +will select a name which satisfies both the rules of the domain system +and any existing rules for the object, whether these rules are published +or implied by existing programs. + +For example, when naming a mail domain, the user should satisfy both the +rules of this memo and those in RFC-822. When creating a new host name, +the old rules for HOSTS.TXT should be followed. This avoids problems +when old software is converted to use domain names. + +The following syntax will result in fewer problems with many + +applications that use domain names (e.g., mail, TELNET). + +<domain> ::= <subdomain> | " " + +<subdomain> ::= <label> | <subdomain> "." <label> + +<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ] + +<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str> + +<let-dig-hyp> ::= <let-dig> | "-" + +<let-dig> ::= <letter> | <digit> + +<letter> ::= any one of the 52 alphabetic characters A through Z in +upper case and a through z in lower case + +<digit> ::= any one of the ten digits 0 through 9 + +Note that while upper and lower case letters are allowed in domain +names, no significance is attached to the case. That is, two names with +the same spelling but different case are to be treated as if identical. + +The labels must follow the rules for ARPANET host names. They must +start with a letter, end with a letter or digit, and have as interior +characters only letters, digits, and hyphen. There are also some +restrictions on the length. Labels must be 63 characters or less. + +For example, the following strings identify hosts in the Internet: + +A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA + +2.3.2. Data Transmission Order + +The order of transmission of the header and data described in this +document is resolved to the octet level. Whenever a diagram shows a + + + +Mockapetris [Page 8] + +RFC 1035 Domain Implementation and Specification November 1987 + + +group of octets, the order of transmission of those octets is the normal +order in which they are read in English. For example, in the following +diagram, the octets are transmitted in the order they are numbered. + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 1 | 2 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 3 | 4 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 5 | 6 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Whenever an octet represents a numeric quantity, the left most bit in +the diagram is the high order or most significant bit. That is, the bit +labeled 0 is the most significant bit. For example, the following +diagram represents the value 170 (decimal). + + 0 1 2 3 4 5 6 7 + +-+-+-+-+-+-+-+-+ + |1 0 1 0 1 0 1 0| + +-+-+-+-+-+-+-+-+ + +Similarly, whenever a multi-octet field represents a numeric quantity +the left most bit of the whole field is the most significant bit. When +a multi-octet quantity is transmitted the most significant octet is +transmitted first. + +2.3.3. Character Case + +For all parts of the DNS that are part of the official protocol, all +comparisons between character strings (e.g., labels, domain names, etc.) +are done in a case-insensitive manner. At present, this rule is in +force throughout the domain system without exception. However, future +additions beyond current usage may need to use the full binary octet +capabilities in names, so attempts to store domain names in 7-bit ASCII +or use of special bytes to terminate labels, etc., should be avoided. + +When data enters the domain system, its original case should be +preserved whenever possible. In certain circumstances this cannot be +done. For example, if two RRs are stored in a database, one at x.y and +one at X.Y, they are actually stored at the same place in the database, +and hence only one casing would be preserved. The basic rule is that +case can be discarded only when data is used to define structure in a +database, and two names are identical when compared in a case +insensitive manner. + + + + +Mockapetris [Page 9] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Loss of case sensitive data must be minimized. Thus while data for x.y +and X.Y may both be stored under a single location x.y or X.Y, data for +a.x and B.X would never be stored under A.x, A.X, b.x, or b.X. In +general, this preserves the case of the first label of a domain name, +but forces standardization of interior node labels. + +Systems administrators who enter data into the domain database should +take care to represent the data they supply to the domain system in a +case-consistent manner if their system is case-sensitive. The data +distribution system in the domain system will ensure that consistent +representations are preserved. + +2.3.4. Size limits + +Various objects and parameters in the DNS have size limits. They are +listed below. Some could be easily changed, others are more +fundamental. + +labels 63 octets or less + +names 255 octets or less + +TTL positive values of a signed 32 bit number. + +UDP messages 512 octets or less + +3. DOMAIN NAME SPACE AND RR DEFINITIONS + +3.1. Name space definitions + +Domain names in messages are expressed in terms of a sequence of labels. +Each label is represented as a one octet length field followed by that +number of octets. Since every domain name ends with the null label of +the root, a domain name is terminated by a length byte of zero. The +high order two bits of every length octet must be zero, and the +remaining six bits of the length field limit the label to 63 octets or +less. + +To simplify implementations, the total length of a domain name (i.e., +label octets and label length octets) is restricted to 255 octets or +less. + +Although labels can contain any 8 bit values in octets that make up a +label, it is strongly recommended that labels follow the preferred +syntax described elsewhere in this memo, which is compatible with +existing host naming conventions. Name servers and resolvers must +compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII +with zero parity. Non-alphabetic codes must match exactly. + + + +Mockapetris [Page 10] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.2. RR definitions + +3.2.1. Format + +All RRs have the same top level format shown below: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +where: + +NAME an owner name, i.e., the name of the node to which this + resource record pertains. + +TYPE two octets containing one of the RR TYPE codes. + +CLASS two octets containing one of the RR CLASS codes. + +TTL a 32 bit signed integer that specifies the time interval + that the resource record may be cached before the source + of the information should again be consulted. Zero + values are interpreted to mean that the RR can only be + used for the transaction in progress, and should not be + cached. For example, SOA records are always distributed + with a zero TTL to prohibit caching. Zero values can + also be used for extremely volatile data. + +RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + + + +Mockapetris [Page 11] + +RFC 1035 Domain Implementation and Specification November 1987 + + +RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + +3.2.2. TYPE values + +TYPE fields are used in resource records. Note that these types are a +subset of QTYPEs. + +TYPE value and meaning + +A 1 a host address + +NS 2 an authoritative name server + +MD 3 a mail destination (Obsolete - use MX) + +MF 4 a mail forwarder (Obsolete - use MX) + +CNAME 5 the canonical name for an alias + +SOA 6 marks the start of a zone of authority + +MB 7 a mailbox domain name (EXPERIMENTAL) + +MG 8 a mail group member (EXPERIMENTAL) + +MR 9 a mail rename domain name (EXPERIMENTAL) + +NULL 10 a null RR (EXPERIMENTAL) + +WKS 11 a well known service description + +PTR 12 a domain name pointer + +HINFO 13 host information + +MINFO 14 mailbox or mail list information + +MX 15 mail exchange + +TXT 16 text strings + +3.2.3. QTYPE values + +QTYPE fields appear in the question part of a query. QTYPES are a +superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the +following QTYPEs are defined: + + + +Mockapetris [Page 12] + +RFC 1035 Domain Implementation and Specification November 1987 + + +AXFR 252 A request for a transfer of an entire zone + +MAILB 253 A request for mailbox-related records (MB, MG or MR) + +MAILA 254 A request for mail agent RRs (Obsolete - see MX) + +* 255 A request for all records + +3.2.4. CLASS values + +CLASS fields appear in resource records. The following CLASS mnemonics +and values are defined: + +IN 1 the Internet + +CS 2 the CSNET class (Obsolete - used only for examples in + some obsolete RFCs) + +CH 3 the CHAOS class + +HS 4 Hesiod [Dyer 87] + +3.2.5. QCLASS values + +QCLASS fields appear in the question section of a query. QCLASS values +are a superset of CLASS values; every CLASS is a valid QCLASS. In +addition to CLASS values, the following QCLASSes are defined: + +* 255 any class + +3.3. Standard RRs + +The following RR definitions are expected to occur, at least +potentially, in all classes. In particular, NS, SOA, CNAME, and PTR +will be used in all classes, and have the same format in all classes. +Because their RDATA format is known, all domain names in the RDATA +section of these RRs may be compressed. + +<domain-name> is a domain name represented as a series of labels, and +terminated by a label with zero length. <character-string> is a single +length octet followed by that number of characters. <character-string> +is treated as binary information, and can be up to 256 characters in +length (including the length octet). + + + + + + + + +Mockapetris [Page 13] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.1. CNAME RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / CNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +CNAME A <domain-name> which specifies the canonical or primary + name for the owner. The owner name is an alias. + +CNAME RRs cause no additional section processing, but name servers may +choose to restart the query at the canonical name in certain cases. See +the description of name server logic in [RFC-1034] for details. + +3.3.2. HINFO RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / CPU / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / OS / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +CPU A <character-string> which specifies the CPU type. + +OS A <character-string> which specifies the operating + system type. + +Standard values for CPU and OS can be found in [RFC-1010]. + +HINFO records are used to acquire general information about a host. The +main use is for protocols such as FTP that can use special procedures +when talking between machines or operating systems of the same type. + +3.3.3. MB RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has the + specified mailbox. + + + +Mockapetris [Page 14] + +RFC 1035 Domain Implementation and Specification November 1987 + + +MB records cause additional section processing which looks up an A type +RRs corresponding to MADNAME. + +3.3.4. MD RDATA format (Obsolete) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has a mail + agent for the domain which should be able to deliver + mail for the domain. + +MD records cause additional section processing which looks up an A type +record corresponding to MADNAME. + +MD is obsolete. See the definition of MX and [RFC-974] for details of +the new scheme. The recommended policy for dealing with MD RRs found in +a master file is to reject them, or to convert them to MX RRs with a +preference of 0. + +3.3.5. MF RDATA format (Obsolete) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has a mail + agent for the domain which will accept mail for + forwarding to the domain. + +MF records cause additional section processing which looks up an A type +record corresponding to MADNAME. + +MF is obsolete. See the definition of MX and [RFC-974] for details ofw +the new scheme. The recommended policy for dealing with MD RRs found in +a master file is to reject them, or to convert them to MX RRs with a +preference of 10. + + + + + + + +Mockapetris [Page 15] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.6. MG RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MGMNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MGMNAME A <domain-name> which specifies a mailbox which is a + member of the mail group specified by the domain name. + +MG records cause no additional section processing. + +3.3.7. MINFO RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / RMAILBX / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / EMAILBX / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +RMAILBX A <domain-name> which specifies a mailbox which is + responsible for the mailing list or mailbox. If this + domain name names the root, the owner of the MINFO RR is + responsible for itself. Note that many existing mailing + lists use a mailbox X-request for the RMAILBX field of + mailing list X, e.g., Msgroup-request for Msgroup. This + field provides a more general mechanism. + + +EMAILBX A <domain-name> which specifies a mailbox which is to + receive error messages related to the mailing list or + mailbox specified by the owner of the MINFO RR (similar + to the ERRORS-TO: field which has been proposed). If + this domain name names the root, errors should be + returned to the sender of the message. + +MINFO records cause no additional section processing. Although these +records can be associated with a simple mailbox, they are usually used +with a mailing list. + + + + + + + + +Mockapetris [Page 16] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.8. MR RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / NEWNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NEWNAME A <domain-name> which specifies a mailbox which is the + proper rename of the specified mailbox. + +MR records cause no additional section processing. The main use for MR +is as a forwarding entry for a user who has moved to a different +mailbox. + +3.3.9. MX RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | PREFERENCE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / EXCHANGE / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +PREFERENCE A 16 bit integer which specifies the preference given to + this RR among others at the same owner. Lower values + are preferred. + +EXCHANGE A <domain-name> which specifies a host willing to act as + a mail exchange for the owner name. + +MX records cause type A additional section processing for the host +specified by EXCHANGE. The use of MX RRs is explained in detail in +[RFC-974]. + +3.3.10. NULL RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / <anything> / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +Anything at all may be in the RDATA field so long as it is 65535 octets +or less. + + + + +Mockapetris [Page 17] + +RFC 1035 Domain Implementation and Specification November 1987 + + +NULL records cause no additional section processing. NULL RRs are not +allowed in master files. NULLs are used as placeholders in some +experimental extensions of the DNS. + +3.3.11. NS RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / NSDNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NSDNAME A <domain-name> which specifies a host which should be + authoritative for the specified class and domain. + +NS records cause both the usual additional section processing to locate +a type A record, and, when used in a referral, a special search of the +zone in which they reside for glue information. + +The NS RR states that the named host should be expected to have a zone +starting at owner name of the specified class. Note that the class may +not indicate the protocol family which should be used to communicate +with the host, although it is typically a strong hint. For example, +hosts which are name servers for either Internet (IN) or Hesiod (HS) +class information are normally queried using IN class protocols. + +3.3.12. PTR RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / PTRDNAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +PTRDNAME A <domain-name> which points to some location in the + domain name space. + +PTR records cause no additional section processing. These RRs are used +in special domains to point to some other location in the domain space. +These records are simple data, and don't imply any special processing +similar to that performed by CNAME, which identifies aliases. See the +description of the IN-ADDR.ARPA domain for an example. + + + + + + + + +Mockapetris [Page 18] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.13. SOA RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / RNAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | SERIAL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | REFRESH | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RETRY | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | EXPIRE | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | MINIMUM | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MNAME The <domain-name> of the name server that was the + original or primary source of data for this zone. + +RNAME A <domain-name> which specifies the mailbox of the + person responsible for this zone. + +SERIAL The unsigned 32 bit version number of the original copy + of the zone. Zone transfers preserve this value. This + value wraps and should be compared using sequence space + arithmetic. + +REFRESH A 32 bit time interval before the zone should be + refreshed. + +RETRY A 32 bit time interval that should elapse before a + failed refresh should be retried. + +EXPIRE A 32 bit time value that specifies the upper limit on + the time interval that can elapse before the zone is no + longer authoritative. + + + + + +Mockapetris [Page 19] + +RFC 1035 Domain Implementation and Specification November 1987 + + +MINIMUM The unsigned 32 bit minimum TTL field that should be + exported with any RR from this zone. + +SOA records cause no additional section processing. + +All times are in units of seconds. + +Most of these fields are pertinent only for name server maintenance +operations. However, MINIMUM is used in all query operations that +retrieve RRs from a zone. Whenever a RR is sent in a response to a +query, the TTL field is set to the maximum of the TTL field from the RR +and the MINIMUM field in the appropriate SOA. Thus MINIMUM is a lower +bound on the TTL field for all RRs in a zone. Note that this use of +MINIMUM should occur when the RRs are copied into the response and not +when the zone is loaded from a master file or via a zone transfer. The +reason for this provison is to allow future dynamic update facilities to +change the SOA RR with known semantics. + + +3.3.14. TXT RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / TXT-DATA / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +TXT-DATA One or more <character-string>s. + +TXT RRs are used to hold descriptive text. The semantics of the text +depends on the domain where it is found. + +3.4. Internet specific RRs + +3.4.1. A RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ADDRESS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ADDRESS A 32 bit Internet address. + +Hosts that have multiple Internet addresses will have multiple A +records. + + + + + +Mockapetris [Page 20] + +RFC 1035 Domain Implementation and Specification November 1987 + + +A records cause no additional section processing. The RDATA section of +an A line in a master file is an Internet address expressed as four +decimal numbers separated by dots without any imbedded spaces (e.g., +"10.2.0.52" or "192.0.5.6"). + +3.4.2. WKS RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ADDRESS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | PROTOCOL | | + +--+--+--+--+--+--+--+--+ | + | | + / <BIT MAP> / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ADDRESS An 32 bit Internet address + +PROTOCOL An 8 bit IP protocol number + +<BIT MAP> A variable length bit map. The bit map must be a + multiple of 8 bits long. + +The WKS record is used to describe the well known services supported by +a particular protocol on a particular internet address. The PROTOCOL +field specifies an IP protocol number, and the bit map has one bit per +port of the specified protocol. The first bit corresponds to port 0, +the second to port 1, etc. If the bit map does not include a bit for a +protocol of interest, that bit is assumed zero. The appropriate values +and mnemonics for ports and protocols are specified in [RFC-1010]. + +For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port +25 (SMTP). If this bit is set, a SMTP server should be listening on TCP +port 25; if zero, SMTP service is not supported on the specified +address. + +The purpose of WKS RRs is to provide availability information for +servers for TCP and UDP. If a server supports both TCP and UDP, or has +multiple Internet addresses, then multiple WKS RRs are used. + +WKS RRs cause no additional section processing. + +In master files, both ports and protocols are expressed using mnemonics +or decimal numbers. + + + + +Mockapetris [Page 21] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.5. IN-ADDR.ARPA domain + +The Internet uses a special domain to support gateway location and +Internet address to host mapping. Other classes may employ a similar +strategy in other domains. The intent of this domain is to provide a +guaranteed method to perform host address to host name mapping, and to +facilitate queries to locate all gateways on a particular network in the +Internet. + +Note that both of these services are similar to functions that could be +performed by inverse queries; the difference is that this part of the +domain name space is structured according to address, and hence can +guarantee that the appropriate data can be located without an exhaustive +search of the domain space. + +The domain begins at IN-ADDR.ARPA and has a substructure which follows +the Internet addressing structure. + +Domain names in the IN-ADDR.ARPA domain are defined to have up to four +labels in addition to the IN-ADDR.ARPA suffix. Each label represents +one octet of an Internet address, and is expressed as a character string +for a decimal value in the range 0-255 (with leading zeros omitted +except in the case of a zero octet which is represented by a single +zero). + +Host addresses are represented by domain names that have all four labels +specified. Thus data for Internet address 10.2.0.52 is located at +domain name 52.0.2.10.IN-ADDR.ARPA. The reversal, though awkward to +read, allows zones to be delegated which are exactly one network of +address space. For example, 10.IN-ADDR.ARPA can be a zone containing +data for the ARPANET, while 26.IN-ADDR.ARPA can be a separate zone for +MILNET. Address nodes are used to hold pointers to primary host names +in the normal domain space. + +Network numbers correspond to some non-terminal nodes at various depths +in the IN-ADDR.ARPA domain, since Internet network numbers are either 1, +2, or 3 octets. Network nodes are used to hold pointers to the primary +host names of gateways attached to that network. Since a gateway is, by +definition, on more than one network, it will typically have two or more +network nodes which point at it. Gateways will also have host level +pointers at their fully qualified addresses. + +Both the gateway pointers at network nodes and the normal host pointers +at full address nodes use the PTR RR to point back to the primary domain +names of the corresponding hosts. + +For example, the IN-ADDR.ARPA domain will contain information about the +ISI gateway between net 10 and 26, an MIT gateway from net 10 to MIT's + + + +Mockapetris [Page 22] + +RFC 1035 Domain Implementation and Specification November 1987 + + +net 18, and hosts A.ISI.EDU and MULTICS.MIT.EDU. Assuming that ISI +gateway has addresses 10.2.0.22 and 26.0.0.103, and a name MILNET- +GW.ISI.EDU, and the MIT gateway has addresses 10.0.0.77 and 18.10.0.4 +and a name GW.LCS.MIT.EDU, the domain database would contain: + + 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 22.0.2.10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 103.0.0.26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 77.0.0.10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 4.0.10.18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 103.0.3.26.IN-ADDR.ARPA. PTR A.ISI.EDU. + 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU. + +Thus a program which wanted to locate gateways on net 10 would originate +a query of the form QTYPE=PTR, QCLASS=IN, QNAME=10.IN-ADDR.ARPA. It +would receive two RRs in response: + + 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + +The program could then originate QTYPE=A, QCLASS=IN queries for MILNET- +GW.ISI.EDU. and GW.LCS.MIT.EDU. to discover the Internet addresses of +these gateways. + +A resolver which wanted to find the host name corresponding to Internet +host address 10.0.0.6 would pursue a query of the form QTYPE=PTR, +QCLASS=IN, QNAME=6.0.0.10.IN-ADDR.ARPA, and would receive: + + 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU. + +Several cautions apply to the use of these services: + - Since the IN-ADDR.ARPA special domain and the normal domain + for a particular host or gateway will be in different zones, + the possibility exists that that the data may be inconsistent. + + - Gateways will often have two names in separate domains, only + one of which can be primary. + + - Systems that use the domain database to initialize their + routing tables must start with enough gateway information to + guarantee that they can access the appropriate name server. + + - The gateway data only reflects the existence of a gateway in a + manner equivalent to the current HOSTS.TXT file. It doesn't + replace the dynamic availability information from GGP or EGP. + + + +Mockapetris [Page 23] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.6. Defining new types, classes, and special namespaces + +The previously defined types and classes are the ones in use as of the +date of this memo. New definitions should be expected. This section +makes some recommendations to designers considering additions to the +existing facilities. The mailing list NAMEDROPPERS@SRI-NIC.ARPA is the +forum where general discussion of design issues takes place. + +In general, a new type is appropriate when new information is to be +added to the database about an existing object, or we need new data +formats for some totally new object. Designers should attempt to define +types and their RDATA formats that are generally applicable to all +classes, and which avoid duplication of information. New classes are +appropriate when the DNS is to be used for a new protocol, etc which +requires new class-specific data formats, or when a copy of the existing +name space is desired, but a separate management domain is necessary. + +New types and classes need mnemonics for master files; the format of the +master files requires that the mnemonics for type and class be disjoint. + +TYPE and CLASS values must be a proper subset of QTYPEs and QCLASSes +respectively. + +The present system uses multiple RRs to represent multiple values of a +type rather than storing multiple values in the RDATA section of a +single RR. This is less efficient for most applications, but does keep +RRs shorter. The multiple RRs assumption is incorporated in some +experimental work on dynamic update methods. + +The present system attempts to minimize the duplication of data in the +database in order to insure consistency. Thus, in order to find the +address of the host for a mail exchange, you map the mail domain name to +a host name, then the host name to addresses, rather than a direct +mapping to host address. This approach is preferred because it avoids +the opportunity for inconsistency. + +In defining a new type of data, multiple RR types should not be used to +create an ordering between entries or express different formats for +equivalent bindings, instead this information should be carried in the +body of the RR and a single type used. This policy avoids problems with +caching multiple types and defining QTYPEs to match multiple types. + +For example, the original form of mail exchange binding used two RR +types one to represent a "closer" exchange (MD) and one to represent a +"less close" exchange (MF). The difficulty is that the presence of one +RR type in a cache doesn't convey any information about the other +because the query which acquired the cached information might have used +a QTYPE of MF, MD, or MAILA (which matched both). The redesigned + + + +Mockapetris [Page 24] + +RFC 1035 Domain Implementation and Specification November 1987 + + +service used a single type (MX) with a "preference" value in the RDATA +section which can order different RRs. However, if any MX RRs are found +in the cache, then all should be there. + +4. MESSAGES + +4.1. Format + +All communications inside of the domain protocol are carried in a single +format called a message. The top level format of message is divided +into 5 sections (some of which are empty in certain cases) shown below: + + +---------------------+ + | Header | + +---------------------+ + | Question | the question for the name server + +---------------------+ + | Answer | RRs answering the question + +---------------------+ + | Authority | RRs pointing toward an authority + +---------------------+ + | Additional | RRs holding additional information + +---------------------+ + +The header section is always present. The header includes fields that +specify which of the remaining sections are present, and also specify +whether the message is a query or a response, a standard query or some +other opcode, etc. + +The names of the sections after the header are derived from their use in +standard queries. The question section contains fields that describe a +question to a name server. These fields are a query type (QTYPE), a +query class (QCLASS), and a query domain name (QNAME). The last three +sections have the same format: a possibly empty list of concatenated +resource records (RRs). The answer section contains RRs that answer the +question; the authority section contains RRs that point toward an +authoritative name server; the additional records section contains RRs +which relate to the query, but are not strictly answers for the +question. + + + + + + + + + + + + +Mockapetris [Page 25] + +RFC 1035 Domain Implementation and Specification November 1987 + + +4.1.1. Header section format + +The header contains the following fields: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ID | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QDCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ANCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | NSCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ARCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ID A 16 bit identifier assigned by the program that + generates any kind of query. This identifier is copied + the corresponding reply and can be used by the requester + to match up replies to outstanding queries. + +QR A one bit field that specifies whether this message is a + query (0), or a response (1). + +OPCODE A four bit field that specifies kind of query in this + message. This value is set by the originator of a query + and copied into the response. The values are: + + 0 a standard query (QUERY) + + 1 an inverse query (IQUERY) + + 2 a server status request (STATUS) + + 3-15 reserved for future use + +AA Authoritative Answer - this bit is valid in responses, + and specifies that the responding name server is an + authority for the domain name in question section. + + Note that the contents of the answer section may have + multiple owner names because of aliases. The AA bit + + + +Mockapetris [Page 26] + +RFC 1035 Domain Implementation and Specification November 1987 + + + corresponds to the name which matches the query name, or + the first owner name in the answer section. + +TC TrunCation - specifies that this message was truncated + due to length greater than that permitted on the + transmission channel. + +RD Recursion Desired - this bit may be set in a query and + is copied into the response. If RD is set, it directs + the name server to pursue the query recursively. + Recursive query support is optional. + +RA Recursion Available - this be is set or cleared in a + response, and denotes whether recursive query support is + available in the name server. + +Z Reserved for future use. Must be zero in all queries + and responses. + +RCODE Response code - this 4 bit field is set as part of + responses. The values have the following + interpretation: + + 0 No error condition + + 1 Format error - The name server was + unable to interpret the query. + + 2 Server failure - The name server was + unable to process this query due to a + problem with the name server. + + 3 Name Error - Meaningful only for + responses from an authoritative name + server, this code signifies that the + domain name referenced in the query does + not exist. + + 4 Not Implemented - The name server does + not support the requested kind of query. + + 5 Refused - The name server refuses to + perform the specified operation for + policy reasons. For example, a name + server may not wish to provide the + information to the particular requester, + or a name server may not wish to perform + a particular operation (e.g., zone + + + +Mockapetris [Page 27] + +RFC 1035 Domain Implementation and Specification November 1987 + + + transfer) for particular data. + + 6-15 Reserved for future use. + +QDCOUNT an unsigned 16 bit integer specifying the number of + entries in the question section. + +ANCOUNT an unsigned 16 bit integer specifying the number of + resource records in the answer section. + +NSCOUNT an unsigned 16 bit integer specifying the number of name + server resource records in the authority records + section. + +ARCOUNT an unsigned 16 bit integer specifying the number of + resource records in the additional records section. + +4.1.2. Question section format + +The question section is used to carry the "question" in most queries, +i.e., the parameters that define what is being asked. The section +contains QDCOUNT (usually 1) entries, each of the following format: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / QNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QTYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QCLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +QNAME a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used. + +QTYPE a two octet code which specifies the type of the query. + The values for this field include all codes valid for a + TYPE field, together with some more general codes which + can match more than one type of RR. + + + +Mockapetris [Page 28] + +RFC 1035 Domain Implementation and Specification November 1987 + + +QCLASS a two octet code that specifies the class of the query. + For example, the QCLASS field is IN for the Internet. + +4.1.3. Resource record format + +The answer, authority, and additional sections all share the same +format: a variable number of resource records, where the number of +records is specified in the corresponding count field in the header. +Each resource record has the following format: + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NAME a domain name to which this resource record pertains. + +TYPE two octets containing one of the RR type codes. This + field specifies the meaning of the data in the RDATA + field. + +CLASS two octets which specify the class of the data in the + RDATA field. + +TTL a 32 bit unsigned integer that specifies the time + interval (in seconds) that the resource record may be + cached before it should be discarded. Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached. + + + + + +Mockapetris [Page 29] + +RFC 1035 Domain Implementation and Specification November 1987 + + +RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + +RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + For example, the if the TYPE is A and the CLASS is IN, + the RDATA field is a 4 octet ARPA Internet address. + +4.1.4. Message compression + +In order to reduce the size of messages, the domain system utilizes a +compression scheme which eliminates the repetition of domain names in a +message. In this scheme, an entire domain name or a list of labels at +the end of a domain name is replaced with a pointer to a prior occurance +of the same name. + +The pointer takes the form of a two octet sequence: + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1| OFFSET | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +The first two bits are ones. This allows a pointer to be distinguished +from a label, since the label must begin with two zero bits because +labels are restricted to 63 octets or less. (The 10 and 01 combinations +are reserved for future use.) The OFFSET field specifies an offset from +the start of the message (i.e., the first octet of the ID field in the +domain header). A zero offset specifies the first byte of the ID field, +etc. + +The compression scheme allows a domain name in a message to be +represented as either: + + - a sequence of labels ending in a zero octet + + - a pointer + + - a sequence of labels ending with a pointer + +Pointers can only be used for occurances of a domain name where the +format is not class specific. If this were not the case, a name server +or resolver would be required to know the format of all RRs it handled. +As yet, there are no such cases, but they may occur in future RDATA +formats. + +If a domain name is contained in a part of the message subject to a +length field (such as the RDATA section of an RR), and compression is + + + +Mockapetris [Page 30] + +RFC 1035 Domain Implementation and Specification November 1987 + + +used, the length of the compressed name is used in the length +calculation, rather than the length of the expanded name. + +Programs are free to avoid using pointers in messages they generate, +although this will reduce datagram capacity, and may cause truncation. +However all programs are required to understand arriving messages that +contain pointers. + +For example, a datagram might need to use the domain names F.ISI.ARPA, +FOO.F.ISI.ARPA, ARPA, and the root. Ignoring the other fields of the +message, these domain names might be represented as: + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 20 | 1 | F | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 22 | 3 | I | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 24 | S | I | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 26 | 4 | A | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 28 | R | P | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 30 | A | 0 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 40 | 3 | F | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 42 | O | O | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 44 | 1 1| 20 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 64 | 1 1| 26 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 92 | 0 | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +The domain name for F.ISI.ARPA is shown at offset 20. The domain name +FOO.F.ISI.ARPA is shown at offset 40; this definition uses a pointer to +concatenate a label for FOO to the previously defined F.ISI.ARPA. The +domain name ARPA is defined at offset 64 using a pointer to the ARPA +component of the name F.ISI.ARPA at 20; note that this pointer relies on +ARPA being the last label in the string at 20. The root domain name is + + + +Mockapetris [Page 31] + +RFC 1035 Domain Implementation and Specification November 1987 + + +defined by a single octet of zeros at 92; the root domain name has no +labels. + +4.2. Transport + +The DNS assumes that messages will be transmitted as datagrams or in a +byte stream carried by a virtual circuit. While virtual circuits can be +used for any DNS activity, datagrams are preferred for queries due to +their lower overhead and better performance. Zone refresh activities +must use virtual circuits because of the need for reliable transfer. + +The Internet supports name server access using TCP [RFC-793] on server +port 53 (decimal) as well as datagram access using UDP [RFC-768] on UDP +port 53 (decimal). + +4.2.1. UDP usage + +Messages sent using UDP user server port 53 (decimal). + +Messages carried by UDP are restricted to 512 bytes (not counting the IP +or UDP headers). Longer messages are truncated and the TC bit is set in +the header. + +UDP is not acceptable for zone transfers, but is the recommended method +for standard queries in the Internet. Queries sent using UDP may be +lost, and hence a retransmission strategy is required. Queries or their +responses may be reordered by the network, or by processing in name +servers, so resolvers should not depend on them being returned in order. + +The optimal UDP retransmission policy will vary with performance of the +Internet and the needs of the client, but the following are recommended: + + - The client should try other servers and server addresses + before repeating a query to a specific address of a server. + + - The retransmission interval should be based on prior + statistics if possible. Too aggressive retransmission can + easily slow responses for the community at large. Depending + on how well connected the client is to its expected servers, + the minimum retransmission interval should be 2-5 seconds. + +More suggestions on server selection and retransmission policy can be +found in the resolver section of this memo. + +4.2.2. TCP usage + +Messages sent over TCP connections use server port 53 (decimal). The +message is prefixed with a two byte length field which gives the message + + + +Mockapetris [Page 32] + +RFC 1035 Domain Implementation and Specification November 1987 + + +length, excluding the two byte length field. This length field allows +the low-level processing to assemble a complete message before beginning +to parse it. + +Several connection management policies are recommended: + + - The server should not block other activities waiting for TCP + data. + + - The server should support multiple connections. + + - The server should assume that the client will initiate + connection closing, and should delay closing its end of the + connection until all outstanding client requests have been + satisfied. + + - If the server needs to close a dormant connection to reclaim + resources, it should wait until the connection has been idle + for a period on the order of two minutes. In particular, the + server should allow the SOA and AXFR request sequence (which + begins a refresh operation) to be made on a single connection. + Since the server would be unable to answer queries anyway, a + unilateral close or reset may be used instead of a graceful + close. + +5. MASTER FILES + +Master files are text files that contain RRs in text form. Since the +contents of a zone can be expressed in the form of a list of RRs a +master file is most often used to define a zone, though it can be used +to list a cache's contents. Hence, this section first discusses the +format of RRs in a master file, and then the special considerations when +a master file is used to create a zone in some name server. + +5.1. Format + +The format of these files is a sequence of entries. Entries are +predominantly line-oriented, though parentheses can be used to continue +a list of items across a line boundary, and text literals can contain +CRLF within the text. Any combination of tabs and spaces act as a +delimiter between the separate items that make up an entry. The end of +any line in the master file can end with a comment. The comment starts +with a ";" (semicolon). + +The following entries are defined: + + <blank>[<comment>] + + + + +Mockapetris [Page 33] + +RFC 1035 Domain Implementation and Specification November 1987 + + + $ORIGIN <domain-name> [<comment>] + + $INCLUDE <file-name> [<domain-name>] [<comment>] + + <domain-name><rr> [<comment>] + + <blank><rr> [<comment>] + +Blank lines, with or without comments, are allowed anywhere in the file. + +Two control entries are defined: $ORIGIN and $INCLUDE. $ORIGIN is +followed by a domain name, and resets the current origin for relative +domain names to the stated name. $INCLUDE inserts the named file into +the current file, and may optionally specify a domain name that sets the +relative domain name origin for the included file. $INCLUDE may also +have a comment. Note that a $INCLUDE entry never changes the relative +origin of the parent file, regardless of changes to the relative origin +made within the included file. + +The last two forms represent RRs. If an entry for an RR begins with a +blank, then the RR is assumed to be owned by the last stated owner. If +an RR entry begins with a <domain-name>, then the owner name is reset. + +<rr> contents take one of the following forms: + + [<TTL>] [<class>] <type> <RDATA> + + [<class>] [<TTL>] <type> <RDATA> + +The RR begins with optional TTL and class fields, followed by a type and +RDATA field appropriate to the type and class. Class and type use the +standard mnemonics, TTL is a decimal integer. Omitted class and TTL +values are default to the last explicitly stated values. Since type and +class mnemonics are disjoint, the parse is unique. (Note that this +order is different from the order used in examples and the order used in +the actual RRs; the given order allows easier parsing and defaulting.) + +<domain-name>s make up a large share of the data in the master file. +The labels in the domain name are expressed as character strings and +separated by dots. Quoting conventions allow arbitrary characters to be +stored in domain names. Domain names that end in a dot are called +absolute, and are taken as complete. Domain names which do not end in a +dot are called relative; the actual domain name is the concatenation of +the relative part with an origin specified in a $ORIGIN, $INCLUDE, or as +an argument to the master file loading routine. A relative name is an +error when no origin is available. + + + + + +Mockapetris [Page 34] + +RFC 1035 Domain Implementation and Specification November 1987 + + +<character-string> is expressed in one or two ways: as a contiguous set +of characters without interior spaces, or as a string beginning with a " +and ending with a ". Inside a " delimited string any character can +occur, except for a " itself, which must be quoted using \ (back slash). + +Because these files are text files several special encodings are +necessary to allow arbitrary data to be loaded. In particular: + + of the root. + +@ A free standing @ is used to denote the current origin. + +\X where X is any character other than a digit (0-9), is + used to quote that character so that its special meaning + does not apply. For example, "\." can be used to place + a dot character in a label. + +\DDD where each D is a digit is the octet corresponding to + the decimal number described by DDD. The resulting + octet is assumed to be text and is not checked for + special meaning. + +( ) Parentheses are used to group data that crosses a line + boundary. In effect, line terminations are not + recognized within parentheses. + +; Semicolon is used to start a comment; the remainder of + the line is ignored. + +5.2. Use of master files to define zones + +When a master file is used to load a zone, the operation should be +suppressed if any errors are encountered in the master file. The +rationale for this is that a single error can have widespread +consequences. For example, suppose that the RRs defining a delegation +have syntax errors; then the server will return authoritative name +errors for all names in the subzone (except in the case where the +subzone is also present on the server). + +Several other validity checks that should be performed in addition to +insuring that the file is syntactically correct: + + 1. All RRs in the file should have the same class. + + 2. Exactly one SOA RR should be present at the top of the zone. + + 3. If delegations are present and glue information is required, + it should be present. + + + +Mockapetris [Page 35] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 4. Information present outside of the authoritative nodes in the + zone should be glue information, rather than the result of an + origin or similar error. + +5.3. Master file example + +The following is an example file which might be used to define the +ISI.EDU zone.and is loaded with an origin of ISI.EDU: + +@ IN SOA VENERA Action\.domains ( + 20 ; SERIAL + 7200 ; REFRESH + 600 ; RETRY + 3600000; EXPIRE + 60) ; MINIMUM + + NS A.ISI.EDU. + NS VENERA + NS VAXA + MX 10 VENERA + MX 20 VAXA + +A A 26.3.0.103 + +VENERA A 10.1.0.52 + A 128.9.0.32 + +VAXA A 10.2.0.27 + A 128.9.0.33 + + +$INCLUDE <SUBSYS>ISI-MAILBOXES.TXT + +Where the file <SUBSYS>ISI-MAILBOXES.TXT is: + + MOE MB A.ISI.EDU. + LARRY MB A.ISI.EDU. + CURLEY MB A.ISI.EDU. + STOOGES MG MOE + MG LARRY + MG CURLEY + +Note the use of the \ character in the SOA RR to specify the responsible +person mailbox "Action.domains@E.ISI.EDU". + + + + + + + +Mockapetris [Page 36] + +RFC 1035 Domain Implementation and Specification November 1987 + + +6. NAME SERVER IMPLEMENTATION + +6.1. Architecture + +The optimal structure for the name server will depend on the host +operating system and whether the name server is integrated with resolver +operations, either by supporting recursive service, or by sharing its +database with a resolver. This section discusses implementation +considerations for a name server which shares a database with a +resolver, but most of these concerns are present in any name server. + +6.1.1. Control + +A name server must employ multiple concurrent activities, whether they +are implemented as separate tasks in the host's OS or multiplexing +inside a single name server program. It is simply not acceptable for a +name server to block the service of UDP requests while it waits for TCP +data for refreshing or query activities. Similarly, a name server +should not attempt to provide recursive service without processing such +requests in parallel, though it may choose to serialize requests from a +single client, or to regard identical requests from the same client as +duplicates. A name server should not substantially delay requests while +it reloads a zone from master files or while it incorporates a newly +refreshed zone into its database. + +6.1.2. Database + +While name server implementations are free to use any internal data +structures they choose, the suggested structure consists of three major +parts: + + - A "catalog" data structure which lists the zones available to + this server, and a "pointer" to the zone data structure. The + main purpose of this structure is to find the nearest ancestor + zone, if any, for arriving standard queries. + + - Separate data structures for each of the zones held by the + name server. + + - A data structure for cached data. (or perhaps separate caches + for different classes) + +All of these data structures can be implemented an identical tree +structure format, with different data chained off the nodes in different +parts: in the catalog the data is pointers to zones, while in the zone +and cache data structures, the data will be RRs. In designing the tree +framework the designer should recognize that query processing will need +to traverse the tree using case-insensitive label comparisons; and that + + + +Mockapetris [Page 37] + +RFC 1035 Domain Implementation and Specification November 1987 + + +in real data, a few nodes have a very high branching factor (100-1000 or +more), but the vast majority have a very low branching factor (0-1). + +One way to solve the case problem is to store the labels for each node +in two pieces: a standardized-case representation of the label where all +ASCII characters are in a single case, together with a bit mask that +denotes which characters are actually of a different case. The +branching factor diversity can be handled using a simple linked list for +a node until the branching factor exceeds some threshold, and +transitioning to a hash structure after the threshold is exceeded. In +any case, hash structures used to store tree sections must insure that +hash functions and procedures preserve the casing conventions of the +DNS. + +The use of separate structures for the different parts of the database +is motivated by several factors: + + - The catalog structure can be an almost static structure that + need change only when the system administrator changes the + zones supported by the server. This structure can also be + used to store parameters used to control refreshing + activities. + + - The individual data structures for zones allow a zone to be + replaced simply by changing a pointer in the catalog. Zone + refresh operations can build a new structure and, when + complete, splice it into the database via a simple pointer + replacement. It is very important that when a zone is + refreshed, queries should not use old and new data + simultaneously. + + - With the proper search procedures, authoritative data in zones + will always "hide", and hence take precedence over, cached + data. + + - Errors in zone definitions that cause overlapping zones, etc., + may cause erroneous responses to queries, but problem + determination is simplified, and the contents of one "bad" + zone can't corrupt another. + + - Since the cache is most frequently updated, it is most + vulnerable to corruption during system restarts. It can also + become full of expired RR data. In either case, it can easily + be discarded without disturbing zone data. + +A major aspect of database design is selecting a structure which allows +the name server to deal with crashes of the name server's host. State +information which a name server should save across system crashes + + + +Mockapetris [Page 38] + +RFC 1035 Domain Implementation and Specification November 1987 + + +includes the catalog structure (including the state of refreshing for +each zone) and the zone data itself. + +6.1.3. Time + +Both the TTL data for RRs and the timing data for refreshing activities +depends on 32 bit timers in units of seconds. Inside the database, +refresh timers and TTLs for cached data conceptually "count down", while +data in the zone stays with constant TTLs. + +A recommended implementation strategy is to store time in two ways: as +a relative increment and as an absolute time. One way to do this is to +use positive 32 bit numbers for one type and negative numbers for the +other. The RRs in zones use relative times; the refresh timers and +cache data use absolute times. Absolute numbers are taken with respect +to some known origin and converted to relative values when placed in the +response to a query. When an absolute TTL is negative after conversion +to relative, then the data is expired and should be ignored. + +6.2. Standard query processing + +The major algorithm for standard query processing is presented in +[RFC-1034]. + +When processing queries with QCLASS=*, or some other QCLASS which +matches multiple classes, the response should never be authoritative +unless the server can guarantee that the response covers all classes. + +When composing a response, RRs which are to be inserted in the +additional section, but duplicate RRs in the answer or authority +sections, may be omitted from the additional section. + +When a response is so long that truncation is required, the truncation +should start at the end of the response and work forward in the +datagram. Thus if there is any data for the authority section, the +answer section is guaranteed to be unique. + +The MINIMUM value in the SOA should be used to set a floor on the TTL of +data distributed from a zone. This floor function should be done when +the data is copied into a response. This will allow future dynamic +update protocols to change the SOA MINIMUM field without ambiguous +semantics. + +6.3. Zone refresh and reload processing + +In spite of a server's best efforts, it may be unable to load zone data +from a master file due to syntax errors, etc., or be unable to refresh a +zone within the its expiration parameter. In this case, the name server + + + +Mockapetris [Page 39] + +RFC 1035 Domain Implementation and Specification November 1987 + + +should answer queries as if it were not supposed to possess the zone. + +If a master is sending a zone out via AXFR, and a new version is created +during the transfer, the master should continue to send the old version +if possible. In any case, it should never send part of one version and +part of another. If completion is not possible, the master should reset +the connection on which the zone transfer is taking place. + +6.4. Inverse queries (Optional) + +Inverse queries are an optional part of the DNS. Name servers are not +required to support any form of inverse queries. If a name server +receives an inverse query that it does not support, it returns an error +response with the "Not Implemented" error set in the header. While +inverse query support is optional, all name servers must be at least +able to return the error response. + +6.4.1. The contents of inverse queries and responses Inverse +queries reverse the mappings performed by standard query operations; +while a standard query maps a domain name to a resource, an inverse +query maps a resource to a domain name. For example, a standard query +might bind a domain name to a host address; the corresponding inverse +query binds the host address to a domain name. + +Inverse queries take the form of a single RR in the answer section of +the message, with an empty question section. The owner name of the +query RR and its TTL are not significant. The response carries +questions in the question section which identify all names possessing +the query RR WHICH THE NAME SERVER KNOWS. Since no name server knows +about all of the domain name space, the response can never be assumed to +be complete. Thus inverse queries are primarily useful for database +management and debugging activities. Inverse queries are NOT an +acceptable method of mapping host addresses to host names; use the IN- +ADDR.ARPA domain instead. + +Where possible, name servers should provide case-insensitive comparisons +for inverse queries. Thus an inverse query asking for an MX RR of +"Venera.isi.edu" should get the same response as a query for +"VENERA.ISI.EDU"; an inverse query for HINFO RR "IBM-PC UNIX" should +produce the same result as an inverse query for "IBM-pc unix". However, +this cannot be guaranteed because name servers may possess RRs that +contain character strings but the name server does not know that the +data is character. + +When a name server processes an inverse query, it either returns: + + 1. zero, one, or multiple domain names for the specified + resource as QNAMEs in the question section + + + +Mockapetris [Page 40] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 2. an error code indicating that the name server doesn't support + inverse mapping of the specified resource type. + +When the response to an inverse query contains one or more QNAMEs, the +owner name and TTL of the RR in the answer section which defines the +inverse query is modified to exactly match an RR found at the first +QNAME. + +RRs returned in the inverse queries cannot be cached using the same +mechanism as is used for the replies to standard queries. One reason +for this is that a name might have multiple RRs of the same type, and +only one would appear. For example, an inverse query for a single +address of a multiply homed host might create the impression that only +one address existed. + +6.4.2. Inverse query and response example The overall structure +of an inverse query for retrieving the domain name that corresponds to +Internet address 10.1.0.52 is shown below: + + +-----------------------------------------+ + Header | OPCODE=IQUERY, ID=997 | + +-----------------------------------------+ + Question | <empty> | + +-----------------------------------------+ + Answer | <anyname> A IN 10.1.0.52 | + +-----------------------------------------+ + Authority | <empty> | + +-----------------------------------------+ + Additional | <empty> | + +-----------------------------------------+ + +This query asks for a question whose answer is the Internet style +address 10.1.0.52. Since the owner name is not known, any domain name +can be used as a placeholder (and is ignored). A single octet of zero, +signifying the root, is usually used because it minimizes the length of +the message. The TTL of the RR is not significant. The response to +this query might be: + + + + + + + + + + + + + + +Mockapetris [Page 41] + +RFC 1035 Domain Implementation and Specification November 1987 + + + +-----------------------------------------+ + Header | OPCODE=RESPONSE, ID=997 | + +-----------------------------------------+ + Question |QTYPE=A, QCLASS=IN, QNAME=VENERA.ISI.EDU | + +-----------------------------------------+ + Answer | VENERA.ISI.EDU A IN 10.1.0.52 | + +-----------------------------------------+ + Authority | <empty> | + +-----------------------------------------+ + Additional | <empty> | + +-----------------------------------------+ + +Note that the QTYPE in a response to an inverse query is the same as the +TYPE field in the answer section of the inverse query. Responses to +inverse queries may contain multiple questions when the inverse is not +unique. If the question section in the response is not empty, then the +RR in the answer section is modified to correspond to be an exact copy +of an RR at the first QNAME. + +6.4.3. Inverse query processing + +Name servers that support inverse queries can support these operations +through exhaustive searches of their databases, but this becomes +impractical as the size of the database increases. An alternative +approach is to invert the database according to the search key. + +For name servers that support multiple zones and a large amount of data, +the recommended approach is separate inversions for each zone. When a +particular zone is changed during a refresh, only its inversions need to +be redone. + +Support for transfer of this type of inversion may be included in future +versions of the domain system, but is not supported in this version. + +6.5. Completion queries and responses + +The optional completion services described in RFC-882 and RFC-883 have +been deleted. Redesigned services may become available in the future. + + + + + + + + + + + + + +Mockapetris [Page 42] + +RFC 1035 Domain Implementation and Specification November 1987 + + +7. RESOLVER IMPLEMENTATION + +The top levels of the recommended resolver algorithm are discussed in +[RFC-1034]. This section discusses implementation details assuming the +database structure suggested in the name server implementation section +of this memo. + +7.1. Transforming a user request into a query + +The first step a resolver takes is to transform the client's request, +stated in a format suitable to the local OS, into a search specification +for RRs at a specific name which match a specific QTYPE and QCLASS. +Where possible, the QTYPE and QCLASS should correspond to a single type +and a single class, because this makes the use of cached data much +simpler. The reason for this is that the presence of data of one type +in a cache doesn't confirm the existence or non-existence of data of +other types, hence the only way to be sure is to consult an +authoritative source. If QCLASS=* is used, then authoritative answers +won't be available. + +Since a resolver must be able to multiplex multiple requests if it is to +perform its function efficiently, each pending request is usually +represented in some block of state information. This state block will +typically contain: + + - A timestamp indicating the time the request began. + The timestamp is used to decide whether RRs in the database + can be used or are out of date. This timestamp uses the + absolute time format previously discussed for RR storage in + zones and caches. Note that when an RRs TTL indicates a + relative time, the RR must be timely, since it is part of a + zone. When the RR has an absolute time, it is part of a + cache, and the TTL of the RR is compared against the timestamp + for the start of the request. + + Note that using the timestamp is superior to using a current + time, since it allows RRs with TTLs of zero to be entered in + the cache in the usual manner, but still used by the current + request, even after intervals of many seconds due to system + load, query retransmission timeouts, etc. + + - Some sort of parameters to limit the amount of work which will + be performed for this request. + + The amount of work which a resolver will do in response to a + client request must be limited to guard against errors in the + database, such as circular CNAME references, and operational + problems, such as network partition which prevents the + + + +Mockapetris [Page 43] + +RFC 1035 Domain Implementation and Specification November 1987 + + + resolver from accessing the name servers it needs. While + local limits on the number of times a resolver will retransmit + a particular query to a particular name server address are + essential, the resolver should have a global per-request + counter to limit work on a single request. The counter should + be set to some initial value and decremented whenever the + resolver performs any action (retransmission timeout, + retransmission, etc.) If the counter passes zero, the request + is terminated with a temporary error. + + Note that if the resolver structure allows one request to + start others in parallel, such as when the need to access a + name server for one request causes a parallel resolve for the + name server's addresses, the spawned request should be started + with a lower counter. This prevents circular references in + the database from starting a chain reaction of resolver + activity. + + - The SLIST data structure discussed in [RFC-1034]. + + This structure keeps track of the state of a request if it + must wait for answers from foreign name servers. + +7.2. Sending the queries + +As described in [RFC-1034], the basic task of the resolver is to +formulate a query which will answer the client's request and direct that +query to name servers which can provide the information. The resolver +will usually only have very strong hints about which servers to ask, in +the form of NS RRs, and may have to revise the query, in response to +CNAMEs, or revise the set of name servers the resolver is asking, in +response to delegation responses which point the resolver to name +servers closer to the desired information. In addition to the +information requested by the client, the resolver may have to call upon +its own services to determine the address of name servers it wishes to +contact. + +In any case, the model used in this memo assumes that the resolver is +multiplexing attention between multiple requests, some from the client, +and some internally generated. Each request is represented by some +state information, and the desired behavior is that the resolver +transmit queries to name servers in a way that maximizes the probability +that the request is answered, minimizes the time that the request takes, +and avoids excessive transmissions. The key algorithm uses the state +information of the request to select the next name server address to +query, and also computes a timeout which will cause the next action +should a response not arrive. The next action will usually be a +transmission to some other server, but may be a temporary error to the + + + +Mockapetris [Page 44] + +RFC 1035 Domain Implementation and Specification November 1987 + + +client. + +The resolver always starts with a list of server names to query (SLIST). +This list will be all NS RRs which correspond to the nearest ancestor +zone that the resolver knows about. To avoid startup problems, the +resolver should have a set of default servers which it will ask should +it have no current NS RRs which are appropriate. The resolver then adds +to SLIST all of the known addresses for the name servers, and may start +parallel requests to acquire the addresses of the servers when the +resolver has the name, but no addresses, for the name servers. + +To complete initialization of SLIST, the resolver attaches whatever +history information it has to the each address in SLIST. This will +usually consist of some sort of weighted averages for the response time +of the address, and the batting average of the address (i.e., how often +the address responded at all to the request). Note that this +information should be kept on a per address basis, rather than on a per +name server basis, because the response time and batting average of a +particular server may vary considerably from address to address. Note +also that this information is actually specific to a resolver address / +server address pair, so a resolver with multiple addresses may wish to +keep separate histories for each of its addresses. Part of this step +must deal with addresses which have no such history; in this case an +expected round trip time of 5-10 seconds should be the worst case, with +lower estimates for the same local network, etc. + +Note that whenever a delegation is followed, the resolver algorithm +reinitializes SLIST. + +The information establishes a partial ranking of the available name +server addresses. Each time an address is chosen and the state should +be altered to prevent its selection again until all other addresses have +been tried. The timeout for each transmission should be 50-100% greater +than the average predicted value to allow for variance in response. + +Some fine points: + + - The resolver may encounter a situation where no addresses are + available for any of the name servers named in SLIST, and + where the servers in the list are precisely those which would + normally be used to look up their own addresses. This + situation typically occurs when the glue address RRs have a + smaller TTL than the NS RRs marking delegation, or when the + resolver caches the result of a NS search. The resolver + should detect this condition and restart the search at the + next ancestor zone, or alternatively at the root. + + + + + +Mockapetris [Page 45] + +RFC 1035 Domain Implementation and Specification November 1987 + + + - If a resolver gets a server error or other bizarre response + from a name server, it should remove it from SLIST, and may + wish to schedule an immediate transmission to the next + candidate server address. + +7.3. Processing responses + +The first step in processing arriving response datagrams is to parse the +response. This procedure should include: + + - Check the header for reasonableness. Discard datagrams which + are queries when responses are expected. + + - Parse the sections of the message, and insure that all RRs are + correctly formatted. + + - As an optional step, check the TTLs of arriving data looking + for RRs with excessively long TTLs. If a RR has an + excessively long TTL, say greater than 1 week, either discard + the whole response, or limit all TTLs in the response to 1 + week. + +The next step is to match the response to a current resolver request. +The recommended strategy is to do a preliminary matching using the ID +field in the domain header, and then to verify that the question section +corresponds to the information currently desired. This requires that +the transmission algorithm devote several bits of the domain ID field to +a request identifier of some sort. This step has several fine points: + + - Some name servers send their responses from different + addresses than the one used to receive the query. That is, a + resolver cannot rely that a response will come from the same + address which it sent the corresponding query to. This name + server bug is typically encountered in UNIX systems. + + - If the resolver retransmits a particular request to a name + server it should be able to use a response from any of the + transmissions. However, if it is using the response to sample + the round trip time to access the name server, it must be able + to determine which transmission matches the response (and keep + transmission times for each outgoing message), or only + calculate round trip times based on initial transmissions. + + - A name server will occasionally not have a current copy of a + zone which it should have according to some NS RRs. The + resolver should simply remove the name server from the current + SLIST, and continue. + + + + +Mockapetris [Page 46] + +RFC 1035 Domain Implementation and Specification November 1987 + + +7.4. Using the cache + +In general, we expect a resolver to cache all data which it receives in +responses since it may be useful in answering future client requests. +However, there are several types of data which should not be cached: + + - When several RRs of the same type are available for a + particular owner name, the resolver should either cache them + all or none at all. When a response is truncated, and a + resolver doesn't know whether it has a complete set, it should + not cache a possibly partial set of RRs. + + - Cached data should never be used in preference to + authoritative data, so if caching would cause this to happen + the data should not be cached. + + - The results of an inverse query should not be cached. + + - The results of standard queries where the QNAME contains "*" + labels if the data might be used to construct wildcards. The + reason is that the cache does not necessarily contain existing + RRs or zone boundary information which is necessary to + restrict the application of the wildcard RRs. + + - RR data in responses of dubious reliability. When a resolver + receives unsolicited responses or RR data other than that + requested, it should discard it without caching it. The basic + implication is that all sanity checks on a packet should be + performed before any of it is cached. + +In a similar vein, when a resolver has a set of RRs for some name in a +response, and wants to cache the RRs, it should check its cache for +already existing RRs. Depending on the circumstances, either the data +in the response or the cache is preferred, but the two should never be +combined. If the data in the response is from authoritative data in the +answer section, it is always preferred. + +8. MAIL SUPPORT + +The domain system defines a standard for mapping mailboxes into domain +names, and two methods for using the mailbox information to derive mail +routing information. The first method is called mail exchange binding +and the other method is mailbox binding. The mailbox encoding standard +and mail exchange binding are part of the DNS official protocol, and are +the recommended method for mail routing in the Internet. Mailbox +binding is an experimental feature which is still under development and +subject to change. + + + + +Mockapetris [Page 47] + +RFC 1035 Domain Implementation and Specification November 1987 + + +The mailbox encoding standard assumes a mailbox name of the form +"<local-part>@<mail-domain>". While the syntax allowed in each of these +sections varies substantially between the various mail internets, the +preferred syntax for the ARPA Internet is given in [RFC-822]. + +The DNS encodes the <local-part> as a single label, and encodes the +<mail-domain> as a domain name. The single label from the <local-part> +is prefaced to the domain name from <mail-domain> to form the domain +name corresponding to the mailbox. Thus the mailbox HOSTMASTER@SRI- +NIC.ARPA is mapped into the domain name HOSTMASTER.SRI-NIC.ARPA. If the +<local-part> contains dots or other special characters, its +representation in a master file will require the use of backslash +quoting to ensure that the domain name is properly encoded. For +example, the mailbox Action.domains@ISI.EDU would be represented as +Action\.domains.ISI.EDU. + +8.1. Mail exchange binding + +Mail exchange binding uses the <mail-domain> part of a mailbox +specification to determine where mail should be sent. The <local-part> +is not even consulted. [RFC-974] specifies this method in detail, and +should be consulted before attempting to use mail exchange support. + +One of the advantages of this method is that it decouples mail +destination naming from the hosts used to support mail service, at the +cost of another layer of indirection in the lookup function. However, +the addition layer should eliminate the need for complicated "%", "!", +etc encodings in <local-part>. + +The essence of the method is that the <mail-domain> is used as a domain +name to locate type MX RRs which list hosts willing to accept mail for +<mail-domain>, together with preference values which rank the hosts +according to an order specified by the administrators for <mail-domain>. + +In this memo, the <mail-domain> ISI.EDU is used in examples, together +with the hosts VENERA.ISI.EDU and VAXA.ISI.EDU as mail exchanges for +ISI.EDU. If a mailer had a message for Mockapetris@ISI.EDU, it would +route it by looking up MX RRs for ISI.EDU. The MX RRs at ISI.EDU name +VENERA.ISI.EDU and VAXA.ISI.EDU, and type A queries can find the host +addresses. + +8.2. Mailbox binding (Experimental) + +In mailbox binding, the mailer uses the entire mail destination +specification to construct a domain name. The encoded domain name for +the mailbox is used as the QNAME field in a QTYPE=MAILB query. + +Several outcomes are possible for this query: + + + +Mockapetris [Page 48] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 1. The query can return a name error indicating that the mailbox + does not exist as a domain name. + + In the long term, this would indicate that the specified + mailbox doesn't exist. However, until the use of mailbox + binding is universal, this error condition should be + interpreted to mean that the organization identified by the + global part does not support mailbox binding. The + appropriate procedure is to revert to exchange binding at + this point. + + 2. The query can return a Mail Rename (MR) RR. + + The MR RR carries new mailbox specification in its RDATA + field. The mailer should replace the old mailbox with the + new one and retry the operation. + + 3. The query can return a MB RR. + + The MB RR carries a domain name for a host in its RDATA + field. The mailer should deliver the message to that host + via whatever protocol is applicable, e.g., b,SMTP. + + 4. The query can return one or more Mail Group (MG) RRs. + + This condition means that the mailbox was actually a mailing + list or mail group, rather than a single mailbox. Each MG RR + has a RDATA field that identifies a mailbox that is a member + of the group. The mailer should deliver a copy of the + message to each member. + + 5. The query can return a MB RR as well as one or more MG RRs. + + This condition means the the mailbox was actually a mailing + list. The mailer can either deliver the message to the host + specified by the MB RR, which will in turn do the delivery to + all members, or the mailer can use the MG RRs to do the + expansion itself. + +In any of these cases, the response may include a Mail Information +(MINFO) RR. This RR is usually associated with a mail group, but is +legal with a MB. The MINFO RR identifies two mailboxes. One of these +identifies a responsible person for the original mailbox name. This +mailbox should be used for requests to be added to a mail group, etc. +The second mailbox name in the MINFO RR identifies a mailbox that should +receive error messages for mail failures. This is particularly +appropriate for mailing lists when errors in member names should be +reported to a person other than the one who sends a message to the list. + + + +Mockapetris [Page 49] + +RFC 1035 Domain Implementation and Specification November 1987 + + +New fields may be added to this RR in the future. + + +9. REFERENCES and BIBLIOGRAPHY + +[Dyer 87] S. Dyer, F. Hsu, "Hesiod", Project Athena + Technical Plan - Name Service, April 1987, version 1.9. + + Describes the fundamentals of the Hesiod name service. + +[IEN-116] J. Postel, "Internet Name Server", IEN-116, + USC/Information Sciences Institute, August 1979. + + A name service obsoleted by the Domain Name System, but + still in use. + +[Quarterman 86] J. Quarterman, and J. Hoskins, "Notable Computer Networks", + Communications of the ACM, October 1986, volume 29, number + 10. + +[RFC-742] K. Harrenstien, "NAME/FINGER", RFC-742, Network + Information Center, SRI International, December 1977. + +[RFC-768] J. Postel, "User Datagram Protocol", RFC-768, + USC/Information Sciences Institute, August 1980. + +[RFC-793] J. Postel, "Transmission Control Protocol", RFC-793, + USC/Information Sciences Institute, September 1981. + +[RFC-799] D. Mills, "Internet Name Domains", RFC-799, COMSAT, + September 1981. + + Suggests introduction of a hierarchy in place of a flat + name space for the Internet. + +[RFC-805] J. Postel, "Computer Mail Meeting Notes", RFC-805, + USC/Information Sciences Institute, February 1982. + +[RFC-810] E. Feinler, K. Harrenstien, Z. Su, and V. White, "DOD + Internet Host Table Specification", RFC-810, Network + Information Center, SRI International, March 1982. + + Obsolete. See RFC-952. + +[RFC-811] K. Harrenstien, V. White, and E. Feinler, "Hostnames + Server", RFC-811, Network Information Center, SRI + International, March 1982. + + + + +Mockapetris [Page 50] + +RFC 1035 Domain Implementation and Specification November 1987 + + + Obsolete. See RFC-953. + +[RFC-812] K. Harrenstien, and V. White, "NICNAME/WHOIS", RFC-812, + Network Information Center, SRI International, March + 1982. + +[RFC-819] Z. Su, and J. Postel, "The Domain Naming Convention for + Internet User Applications", RFC-819, Network + Information Center, SRI International, August 1982. + + Early thoughts on the design of the domain system. + Current implementation is completely different. + +[RFC-821] J. Postel, "Simple Mail Transfer Protocol", RFC-821, + USC/Information Sciences Institute, August 1980. + +[RFC-830] Z. Su, "A Distributed System for Internet Name Service", + RFC-830, Network Information Center, SRI International, + October 1982. + + Early thoughts on the design of the domain system. + Current implementation is completely different. + +[RFC-882] P. Mockapetris, "Domain names - Concepts and + Facilities," RFC-882, USC/Information Sciences + Institute, November 1983. + + Superceeded by this memo. + +[RFC-883] P. Mockapetris, "Domain names - Implementation and + Specification," RFC-883, USC/Information Sciences + Institute, November 1983. + + Superceeded by this memo. + +[RFC-920] J. Postel and J. Reynolds, "Domain Requirements", + RFC-920, USC/Information Sciences Institute, + October 1984. + + Explains the naming scheme for top level domains. + +[RFC-952] K. Harrenstien, M. Stahl, E. Feinler, "DoD Internet Host + Table Specification", RFC-952, SRI, October 1985. + + Specifies the format of HOSTS.TXT, the host/address + table replaced by the DNS. + + + + + +Mockapetris [Page 51] + +RFC 1035 Domain Implementation and Specification November 1987 + + +[RFC-953] K. Harrenstien, M. Stahl, E. Feinler, "HOSTNAME Server", + RFC-953, SRI, October 1985. + + This RFC contains the official specification of the + hostname server protocol, which is obsoleted by the DNS. + This TCP based protocol accesses information stored in + the RFC-952 format, and is used to obtain copies of the + host table. + +[RFC-973] P. Mockapetris, "Domain System Changes and + Observations", RFC-973, USC/Information Sciences + Institute, January 1986. + + Describes changes to RFC-882 and RFC-883 and reasons for + them. + +[RFC-974] C. Partridge, "Mail routing and the domain system", + RFC-974, CSNET CIC BBN Labs, January 1986. + + Describes the transition from HOSTS.TXT based mail + addressing to the more powerful MX system used with the + domain system. + +[RFC-1001] NetBIOS Working Group, "Protocol standard for a NetBIOS + service on a TCP/UDP transport: Concepts and Methods", + RFC-1001, March 1987. + + This RFC and RFC-1002 are a preliminary design for + NETBIOS on top of TCP/IP which proposes to base NetBIOS + name service on top of the DNS. + +[RFC-1002] NetBIOS Working Group, "Protocol standard for a NetBIOS + service on a TCP/UDP transport: Detailed + Specifications", RFC-1002, March 1987. + +[RFC-1010] J. Reynolds, and J. Postel, "Assigned Numbers", RFC-1010, + USC/Information Sciences Institute, May 1987. + + Contains socket numbers and mnemonics for host names, + operating systems, etc. + +[RFC-1031] W. Lazear, "MILNET Name Domain Transition", RFC-1031, + November 1987. + + Describes a plan for converting the MILNET to the DNS. + +[RFC-1032] M. Stahl, "Establishing a Domain - Guidelines for + Administrators", RFC-1032, November 1987. + + + +Mockapetris [Page 52] + +RFC 1035 Domain Implementation and Specification November 1987 + + + Describes the registration policies used by the NIC to + administer the top level domains and delegate subzones. + +[RFC-1033] M. Lottor, "Domain Administrators Operations Guide", + RFC-1033, November 1987. + + A cookbook for domain administrators. + +[Solomon 82] M. Solomon, L. Landweber, and D. Neuhengen, "The CSNET + Name Server", Computer Networks, vol 6, nr 3, July 1982. + + Describes a name service for CSNET which is independent + from the DNS and DNS use in the CSNET. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Mockapetris [Page 53] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Index + + * 13 + + ; 33, 35 + + <character-string> 35 + <domain-name> 34 + + @ 35 + + \ 35 + + A 12 + + Byte order 8 + + CH 13 + Character case 9 + CLASS 11 + CNAME 12 + Completion 42 + CS 13 + + Hesiod 13 + HINFO 12 + HS 13 + + IN 13 + IN-ADDR.ARPA domain 22 + Inverse queries 40 + + Mailbox names 47 + MB 12 + MD 12 + MF 12 + MG 12 + MINFO 12 + MINIMUM 20 + MR 12 + MX 12 + + NS 12 + NULL 12 + + Port numbers 32 + Primary server 5 + PTR 12, 18 + + + +Mockapetris [Page 54] + +RFC 1035 Domain Implementation and Specification November 1987 + + + QCLASS 13 + QTYPE 12 + + RDATA 12 + RDLENGTH 11 + + Secondary server 5 + SOA 12 + Stub resolvers 7 + + TCP 32 + TXT 12 + TYPE 11 + + UDP 32 + + WKS 12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Mockapetris [Page 55] + diff --git a/lib/dns/tests/testdata/dst/test1.dsasig b/lib/dns/tests/testdata/dst/test1.dsasig new file mode 100644 index 0000000..5dd12e1 --- /dev/null +++ b/lib/dns/tests/testdata/dst/test1.dsasig @@ -0,0 +1,3 @@ +0009B55FDB62034326278C9371F32D92 +3D0E1161A32D491BEC38546FC452D903 +A91D806345B2F7F22E diff --git a/lib/dns/tests/testdata/dst/test1.rsasig b/lib/dns/tests/testdata/dst/test1.rsasig new file mode 100644 index 0000000..5ba62b4 --- /dev/null +++ b/lib/dns/tests/testdata/dst/test1.rsasig @@ -0,0 +1,5 @@ +A8A20D2F26F792B3CE76DD0E12A85DFE +FF66AB866EF0BDB0F515001E234E699B +F5CD6FB41FB15D4213705ABE9B563896 +2196228648E0F8AA7F2F4EED3C19165C +1B4C70C9D69B93A1F2BE5B2F948CE023 diff --git a/lib/dns/tests/testdata/dst/test2.data b/lib/dns/tests/testdata/dst/test2.data new file mode 100644 index 0000000..7b0e35d --- /dev/null +++ b/lib/dns/tests/testdata/dst/test2.data @@ -0,0 +1,3077 @@ +Network Working Group P. Mockapetris +Request for Comments: 1035 ISI + November 1987 +Obsoletes: RFCs 882, 883, 973 + + DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION + + +1. STATUS OF THIS MEMO + +This RFC describes the details of the domain system and protocol, and +assumes that the reader is familiar with the concepts discussed in a +companion RFC, "Domain Names - Concepts and Facilities" [RFC-4301]. + +The domain system is a mixture of functions and data types which are an +official protocol and functions and data types which are still +experimental. Since the domain system is intentionally extensible, new +data types and experimental behavior should always be expected in parts +of the system beyond the official protocol. The official protocol parts +include standard queries, responses and the Internet class RR data +formats (e.g., host addresses). Since the previous RFC set, several +definitions have changed, so some previous definitions are obsolete. + +Experimental or obsolete features are clearly marked in these RFCs, and +such information should be used with caution. + +The reader is especially cautioned not to depend on the values which +appear in examples to be current or complete, since their purpose is +primarily pedagogical. Distribution of this memo is unlimited. + + Table of Contents + + 1. STATUS OF THIS MEMO 1 + 2. INTRODUCTION 3 + 2.1. Overview 3 + 2.2. Common configurations 4 + 2.3. Conventions 7 + 2.3.1. Preferred name syntax 7 + 2.3.2. Data Transmission Order 8 + 2.3.3. Character Case 9 + 2.3.4. Size limits 10 + 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10 + 3.1. Name space definitions 10 + 3.2. RR definitions 11 + 3.2.1. Format 11 + 3.2.2. TYPE values 12 + 3.2.3. QTYPE values 12 + 3.2.4. CLASS values 13 + + + +Mockapetris [Page 1] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 3.2.5. QCLASS values 13 + 3.3. Standard RRs 13 + 3.3.1. CNAME RDATA format 14 + 3.3.2. HINFO RDATA format 14 + 3.3.3. MB RDATA format (EXPERIMENTAL) 14 + 3.3.4. MD RDATA format (Obsolete) 15 + 3.3.5. MF RDATA format (Obsolete) 15 + 3.3.6. MG RDATA format (EXPERIMENTAL) 16 + 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16 + 3.3.8. MR RDATA format (EXPERIMENTAL) 17 + 3.3.9. MX RDATA format 17 + 3.3.10. NULL RDATA format (EXPERIMENTAL) 17 + 3.3.11. NS RDATA format 18 + 3.3.12. PTR RDATA format 18 + 3.3.13. SOA RDATA format 19 + 3.3.14. TXT RDATA format 20 + 3.4. ARPA Internet specific RRs 20 + 3.4.1. A RDATA format 20 + 3.4.2. WKS RDATA format 21 + 3.5. IN-ADDR.ARPA domain 22 + 3.6. Defining new types, classes, and special namespaces 24 + 4. MESSAGES 25 + 4.1. Format 25 + 4.1.1. Header section format 26 + 4.1.2. Question section format 28 + 4.1.3. Resource record format 29 + 4.1.4. Message compression 30 + 4.2. Transport 32 + 4.2.1. UDP usage 32 + 4.2.2. TCP usage 32 + 5. MASTER FILES 33 + 5.1. Format 33 + 5.2. Use of master files to define zones 35 + 5.3. Master file example 36 + 6. NAME SERVER IMPLEMENTATION 37 + 6.1. Architecture 37 + 6.1.1. Control 37 + 6.1.2. Database 37 + 6.1.3. Time 39 + 6.2. Standard query processing 39 + 6.3. Zone refresh and reload processing 39 + 6.4. Inverse queries (Optional) 40 + 6.4.1. The contents of inverse queries and responses 40 + 6.4.2. Inverse query and response example 41 + 6.4.3. Inverse query processing 42 + + + + + + +Mockapetris [Page 2] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 6.5. Completion queries and responses 42 + 7. RESOLVER IMPLEMENTATION 43 + 7.1. Transforming a user request into a query 43 + 7.2. Sending the queries 44 + 7.3. Processing responses 46 + 7.4. Using the cache 47 + 8. MAIL SUPPORT 47 + 8.1. Mail exchange binding 48 + 8.2. Mailbox binding (Experimental) 48 + 9. REFERENCES and BIBLIOGRAPHY 50 + Index 54 + +2. INTRODUCTION + +2.1. Overview + +The goal of domain names is to provide a mechanism for naming resources +in such a way that the names are usable in different hosts, networks, +protocol families, internets, and administrative organizations. + +From the user's point of view, domain names are useful as arguments to a +local agent, called a resolver, which retrieves information associated +with the domain name. Thus a user might ask for the host address or +mail information associated with a particular domain name. To enable +the user to request a particular type of information, an appropriate +query type is passed to the resolver with the domain name. To the user, +the domain tree is a single information space; the resolver is +responsible for hiding the distribution of data among name servers from +the user. + +From the resolver's point of view, the database that makes up the domain +space is distributed among various name servers. Different parts of the +domain space are stored in different name servers, although a particular +data item will be stored redundantly in two or more name servers. The +resolver starts with knowledge of at least one name server. When the +resolver processes a user query it asks a known name server for the +information; in return, the resolver either receives the desired +information or a referral to another name server. Using these +referrals, resolvers learn the identities and contents of other name +servers. Resolvers are responsible for dealing with the distribution of +the domain space and dealing with the effects of name server failure by +consulting redundant databases in other servers. + +Name servers manage two kinds of data. The first kind of data held in +sets called zones; each zone is the complete database for a particular +"pruned" subtree of the domain space. This data is called +authoritative. A name server periodically checks to make sure that its +zones are up to date, and if not, obtains a new copy of updated zones + + + +Mockapetris [Page 3] + +RFC 1035 Domain Implementation and Specification November 1987 + + +from master files stored locally or in another name server. The second +kind of data is cached data which was acquired by a local resolver. +This data may be incomplete, but improves the performance of the +retrieval process when non-local data is repeatedly accessed. Cached +data is eventually discarded by a timeout mechanism. + +This functional structure isolates the problems of user interface, +failure recovery, and distribution in the resolvers and isolates the +database update and refresh problems in the name servers. + +2.2. Common configurations + +A host can participate in the domain name system in a number of ways, +depending on whether the host runs programs that retrieve information +from the domain system, name servers that answer queries from other +hosts, or various combinations of both functions. The simplest, and +perhaps most typical, configuration is shown below: + + Local Host | Foreign + | + +---------+ +----------+ | +--------+ + | | user queries | |queries | | | + | User |-------------->| |---------|->|Foreign | + | Program | | Resolver | | | Name | + | |<--------------| |<--------|--| Server | + | | user responses| |responses| | | + +---------+ +----------+ | +--------+ + | A | + cache additions | | references | + V | | + +----------+ | + | cache | | + +----------+ | + +User programs interact with the domain name space through resolvers; the +format of user queries and user responses is specific to the host and +its operating system. User queries will typically be operating system +calls, and the resolver and its cache will be part of the host operating +system. Less capable hosts may choose to implement the resolver as a +subroutine to be linked in with every program that needs its services. +Resolvers answer user queries with information they acquire via queries +to foreign name servers and the local cache. + +Note that the resolver may have to make several queries to several +different foreign name servers to answer a particular user query, and +hence the resolution of a user query may involve several network +accesses and an arbitrary amount of time. The queries to foreign name +servers and the corresponding responses have a standard format described + + + +Mockapetris [Page 4] + +RFC 1035 Domain Implementation and Specification November 1987 + + +in this memo, and may be datagrams. + +Depending on its capabilities, a name server could be a stand alone +program on a dedicated machine or a process or processes on a large +timeshared host. A simple configuration might be: + + Local Host | Foreign + | + +---------+ | + / /| | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + +Here a primary name server acquires information about one or more zones +by reading master files from its local file system, and answers queries +about those zones that arrive from foreign resolvers. + +The DNS requires that all zones be redundantly supported by more than +one name server. Designated secondary servers can acquire zones and +check for updates from the primary server using the zone transfer +protocol of the DNS. This configuration is shown below: + + Local Host | Foreign + | + +---------+ | + / /| | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + A |maintenance | +--------+ + | +------------|->| | + | queries | |Foreign | + | | | Name | + +------------------|--| Server | + maintenance responses | +--------+ + +In this configuration, the name server periodically establishes a +virtual circuit to a foreign name server to acquire a copy of a zone or +to check that an existing copy has not changed. The messages sent for + + + +Mockapetris [Page 5] + +RFC 1035 Domain Implementation and Specification November 1987 + + +these maintenance activities follow the same form as queries and +responses, but the message sequences are somewhat different. + +The information flow in a host that supports all aspects of the domain +name system is shown below: + + Local Host | Foreign + | + +---------+ +----------+ | +--------+ + | | user queries | |queries | | | + | User |-------------->| |---------|->|Foreign | + | Program | | Resolver | | | Name | + | |<--------------| |<--------|--| Server | + | | user responses| |responses| | | + +---------+ +----------+ | +--------+ + | A | + cache additions | | references | + V | | + +----------+ | + | Shared | | + | database | | + +----------+ | + A | | + +---------+ refreshes | | references | + / /| | V | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + A |maintenance | +--------+ + | +------------|->| | + | queries | |Foreign | + | | | Name | + +------------------|--| Server | + maintenance responses | +--------+ + +The shared database holds domain space data for the local name server +and resolver. The contents of the shared database will typically be a +mixture of authoritative data maintained by the periodic refresh +operations of the name server and cached data from previous resolver +requests. The structure of the domain data and the necessity for +synchronization between name servers and resolvers imply the general +characteristics of this database, but the actual format is up to the +local implementor. + + + + +Mockapetris [Page 6] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Information flow can also be tailored so that a group of hosts act +together to optimize activities. Sometimes this is done to offload less +capable hosts so that they do not have to implement a full resolver. +This can be appropriate for PCs or hosts which want to minimize the +amount of new network code which is required. This scheme can also +allow a group of hosts can share a small number of caches rather than +maintaining a large number of separate caches, on the premise that the +centralized caches will have a higher hit ratio. In either case, +resolvers are replaced with stub resolvers which act as front ends to +resolvers located in a recursive server in one or more name servers +known to perform that service: + + Local Hosts | Foreign + | + +---------+ | + | | responses | + | Stub |<--------------------+ | + | Resolver| | | + | |----------------+ | | + +---------+ recursive | | | + queries | | | + V | | + +---------+ recursive +----------+ | +--------+ + | | queries | |queries | | | + | Stub |-------------->| Recursive|---------|->|Foreign | + | Resolver| | Server | | | Name | + | |<--------------| |<--------|--| Server | + +---------+ responses | |responses| | | + +----------+ | +--------+ + | Central | | + | cache | | + +----------+ | + +In any case, note that domain components are always replicated for +reliability whenever possible. + +2.3. Conventions + +The domain system has several conventions dealing with low-level, but +fundamental, issues. While the implementor is free to violate these +conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in +ALL behavior observed from other hosts. + +2.3.1. Preferred name syntax + +The DNS specifications attempt to be as general as possible in the rules +for constructing domain names. The idea is that the name of any +existing object can be expressed as a domain name with minimal changes. + + + +Mockapetris [Page 7] + +RFC 1035 Domain Implementation and Specification November 1987 + + +However, when assigning a domain name for an object, the prudent user +will select a name which satisfies both the rules of the domain system +and any existing rules for the object, whether these rules are published +or implied by existing programs. + +For example, when naming a mail domain, the user should satisfy both the +rules of this memo and those in RFC-822. When creating a new host name, +the old rules for HOSTS.TXT should be followed. This avoids problems +when old software is converted to use domain names. + +The following syntax will result in fewer problems with many + +applications that use domain names (e.g., mail, TELNET). + +<domain> ::= <subdomain> | " " + +<subdomain> ::= <label> | <subdomain> "." <label> + +<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ] + +<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str> + +<let-dig-hyp> ::= <let-dig> | "-" + +<let-dig> ::= <letter> | <digit> + +<letter> ::= any one of the 52 alphabetic characters A through Z in +upper case and a through z in lower case + +<digit> ::= any one of the ten digits 0 through 9 + +Note that while upper and lower case letters are allowed in domain +names, no significance is attached to the case. That is, two names with +the same spelling but different case are to be treated as if identical. + +The labels must follow the rules for ARPANET host names. They must +start with a letter, end with a letter or digit, and have as interior +characters only letters, digits, and hyphen. There are also some +restrictions on the length. Labels must be 63 characters or less. + +For example, the following strings identify hosts in the Internet: + +A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA + +2.3.2. Data Transmission Order + +The order of transmission of the header and data described in this +document is resolved to the octet level. Whenever a diagram shows a + + + +Mockapetris [Page 8] + +RFC 1035 Domain Implementation and Specification November 1987 + + +group of octets, the order of transmission of those octets is the normal +order in which they are read in English. For example, in the following +diagram, the octets are transmitted in the order they are numbered. + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 1 | 2 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 3 | 4 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 5 | 6 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Whenever an octet represents a numeric quantity, the left most bit in +the diagram is the high order or most significant bit. That is, the bit +labeled 0 is the most significant bit. For example, the following +diagram represents the value 170 (decimal). + + 0 1 2 3 4 5 6 7 + +-+-+-+-+-+-+-+-+ + |1 0 1 0 1 0 1 0| + +-+-+-+-+-+-+-+-+ + +Similarly, whenever a multi-octet field represents a numeric quantity +the left most bit of the whole field is the most significant bit. When +a multi-octet quantity is transmitted the most significant octet is +transmitted first. + +2.3.3. Character Case + +For all parts of the DNS that are part of the official protocol, all +comparisons between character strings (e.g., labels, domain names, etc.) +are done in a case-insensitive manner. At present, this rule is in +force throughout the domain system without exception. However, future +additions beyond current usage may need to use the full binary octet +capabilities in names, so attempts to store domain names in 7-bit ASCII +or use of special bytes to terminate labels, etc., should be avoided. + +When data enters the domain system, its original case should be +preserved whenever possible. In certain circumstances this cannot be +done. For example, if two RRs are stored in a database, one at x.y and +one at X.Y, they are actually stored at the same place in the database, +and hence only one casing would be preserved. The basic rule is that +case can be discarded only when data is used to define structure in a +database, and two names are identical when compared in a case +insensitive manner. + + + + +Mockapetris [Page 9] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Loss of case sensitive data must be minimized. Thus while data for x.y +and X.Y may both be stored under a single location x.y or X.Y, data for +a.x and B.X would never be stored under A.x, A.X, b.x, or b.X. In +general, this preserves the case of the first label of a domain name, +but forces standardization of interior node labels. + +Systems administrators who enter data into the domain database should +take care to represent the data they supply to the domain system in a +case-consistent manner if their system is case-sensitive. The data +distribution system in the domain system will ensure that consistent +representations are preserved. + +2.3.4. Size limits + +Various objects and parameters in the DNS have size limits. They are +listed below. Some could be easily changed, others are more +fundamental. + +labels 63 octets or less + +names 255 octets or less + +TTL positive values of a signed 32 bit number. + +UDP messages 512 octets or less + +3. DOMAIN NAME SPACE AND RR DEFINITIONS + +3.1. Name space definitions + +Domain names in messages are expressed in terms of a sequence of labels. +Each label is represented as a one octet length field followed by that +number of octets. Since every domain name ends with the null label of +the root, a domain name is terminated by a length byte of zero. The +high order two bits of every length octet must be zero, and the +remaining six bits of the length field limit the label to 63 octets or +less. + +To simplify implementations, the total length of a domain name (i.e., +label octets and label length octets) is restricted to 255 octets or +less. + +Although labels can contain any 8 bit values in octets that make up a +label, it is strongly recommended that labels follow the preferred +syntax described elsewhere in this memo, which is compatible with +existing host naming conventions. Name servers and resolvers must +compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII +with zero parity. Non-alphabetic codes must match exactly. + + + +Mockapetris [Page 10] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.2. RR definitions + +3.2.1. Format + +All RRs have the same top level format shown below: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +where: + +NAME an owner name, i.e., the name of the node to which this + resource record pertains. + +TYPE two octets containing one of the RR TYPE codes. + +CLASS two octets containing one of the RR CLASS codes. + +TTL a 32 bit signed integer that specifies the time interval + that the resource record may be cached before the source + of the information should again be consulted. Zero + values are interpreted to mean that the RR can only be + used for the transaction in progress, and should not be + cached. For example, SOA records are always distributed + with a zero TTL to prohibit caching. Zero values can + also be used for extremely volatile data. + +RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + + + +Mockapetris [Page 11] + +RFC 1035 Domain Implementation and Specification November 1987 + + +RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + +3.2.2. TYPE values + +TYPE fields are used in resource records. Note that these types are a +subset of QTYPEs. + +TYPE value and meaning + +A 1 a host address + +NS 2 an authoritative name server + +MD 3 a mail destination (Obsolete - use MX) + +MF 4 a mail forwarder (Obsolete - use MX) + +CNAME 5 the canonical name for an alias + +SOA 6 marks the start of a zone of authority + +MB 7 a mailbox domain name (EXPERIMENTAL) + +MG 8 a mail group member (EXPERIMENTAL) + +MR 9 a mail rename domain name (EXPERIMENTAL) + +NULL 10 a null RR (EXPERIMENTAL) + +WKS 11 a well known service description + +PTR 12 a domain name pointer + +HINFO 13 host information + +MINFO 14 mailbox or mail list information + +MX 15 mail exchange + +TXT 16 text strings + +3.2.3. QTYPE values + +QTYPE fields appear in the question part of a query. QTYPES are a +superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the +following QTYPEs are defined: + + + +Mockapetris [Page 12] + +RFC 1035 Domain Implementation and Specification November 1987 + + +AXFR 252 A request for a transfer of an entire zone + +MAILB 253 A request for mailbox-related records (MB, MG or MR) + +MAILA 254 A request for mail agent RRs (Obsolete - see MX) + +* 255 A request for all records + +3.2.4. CLASS values + +CLASS fields appear in resource records. The following CLASS mnemonics +and values are defined: + +IN 1 the Internet + +CS 2 the CSNET class (Obsolete - used only for examples in + some obsolete RFCs) + +CH 3 the CHAOS class + +HS 4 Hesiod [Dyer 87] + +3.2.5. QCLASS values + +QCLASS fields appear in the question section of a query. QCLASS values +are a superset of CLASS values; every CLASS is a valid QCLASS. In +addition to CLASS values, the following QCLASSes are defined: + +* 255 any class + +3.3. Standard RRs + +The following RR definitions are expected to occur, at least +potentially, in all classes. In particular, NS, SOA, CNAME, and PTR +will be used in all classes, and have the same format in all classes. +Because their RDATA format is known, all domain names in the RDATA +section of these RRs may be compressed. + +<domain-name> is a domain name represented as a series of labels, and +terminated by a label with zero length. <character-string> is a single +length octet followed by that number of characters. <character-string> +is treated as binary information, and can be up to 256 characters in +length (including the length octet). + + + + + + + + +Mockapetris [Page 13] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.1. CNAME RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / CNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +CNAME A <domain-name> which specifies the canonical or primary + name for the owner. The owner name is an alias. + +CNAME RRs cause no additional section processing, but name servers may +choose to restart the query at the canonical name in certain cases. See +the description of name server logic in [RFC-1034] for details. + +3.3.2. HINFO RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / CPU / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / OS / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +CPU A <character-string> which specifies the CPU type. + +OS A <character-string> which specifies the operating + system type. + +Standard values for CPU and OS can be found in [RFC-1010]. + +HINFO records are used to acquire general information about a host. The +main use is for protocols such as FTP that can use special procedures +when talking between machines or operating systems of the same type. + +3.3.3. MB RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has the + specified mailbox. + + + +Mockapetris [Page 14] + +RFC 1035 Domain Implementation and Specification November 1987 + + +MB records cause additional section processing which looks up an A type +RRs corresponding to MADNAME. + +3.3.4. MD RDATA format (Obsolete) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has a mail + agent for the domain which should be able to deliver + mail for the domain. + +MD records cause additional section processing which looks up an A type +record corresponding to MADNAME. + +MD is obsolete. See the definition of MX and [RFC-974] for details of +the new scheme. The recommended policy for dealing with MD RRs found in +a master file is to reject them, or to convert them to MX RRs with a +preference of 0. + +3.3.5. MF RDATA format (Obsolete) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has a mail + agent for the domain which will accept mail for + forwarding to the domain. + +MF records cause additional section processing which looks up an A type +record corresponding to MADNAME. + +MF is obsolete. See the definition of MX and [RFC-974] for details ofw +the new scheme. The recommended policy for dealing with MD RRs found in +a master file is to reject them, or to convert them to MX RRs with a +preference of 10. + + + + + + + +Mockapetris [Page 15] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.6. MG RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MGMNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MGMNAME A <domain-name> which specifies a mailbox which is a + member of the mail group specified by the domain name. + +MG records cause no additional section processing. + +3.3.7. MINFO RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / RMAILBX / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / EMAILBX / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +RMAILBX A <domain-name> which specifies a mailbox which is + responsible for the mailing list or mailbox. If this + domain name names the root, the owner of the MINFO RR is + responsible for itself. Note that many existing mailing + lists use a mailbox X-request for the RMAILBX field of + mailing list X, e.g., Msgroup-request for Msgroup. This + field provides a more general mechanism. + + +EMAILBX A <domain-name> which specifies a mailbox which is to + receive error messages related to the mailing list or + mailbox specified by the owner of the MINFO RR (similar + to the ERRORS-TO: field which has been proposed). If + this domain name names the root, errors should be + returned to the sender of the message. + +MINFO records cause no additional section processing. Although these +records can be associated with a simple mailbox, they are usually used +with a mailing list. + + + + + + + + +Mockapetris [Page 16] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.8. MR RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / NEWNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NEWNAME A <domain-name> which specifies a mailbox which is the + proper rename of the specified mailbox. + +MR records cause no additional section processing. The main use for MR +is as a forwarding entry for a user who has moved to a different +mailbox. + +3.3.9. MX RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | PREFERENCE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / EXCHANGE / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +PREFERENCE A 16 bit integer which specifies the preference given to + this RR among others at the same owner. Lower values + are preferred. + +EXCHANGE A <domain-name> which specifies a host willing to act as + a mail exchange for the owner name. + +MX records cause type A additional section processing for the host +specified by EXCHANGE. The use of MX RRs is explained in detail in +[RFC-974]. + +3.3.10. NULL RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / <anything> / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +Anything at all may be in the RDATA field so long as it is 65535 octets +or less. + + + + +Mockapetris [Page 17] + +RFC 1035 Domain Implementation and Specification November 1987 + + +NULL records cause no additional section processing. NULL RRs are not +allowed in master files. NULLs are used as placeholders in some +experimental extensions of the DNS. + +3.3.11. NS RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / NSDNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NSDNAME A <domain-name> which specifies a host which should be + authoritative for the specified class and domain. + +NS records cause both the usual additional section processing to locate +a type A record, and, when used in a referral, a special search of the +zone in which they reside for glue information. + +The NS RR states that the named host should be expected to have a zone +starting at owner name of the specified class. Note that the class may +not indicate the protocol family which should be used to communicate +with the host, although it is typically a strong hint. For example, +hosts which are name servers for either Internet (IN) or Hesiod (HS) +class information are normally queried using IN class protocols. + +3.3.12. PTR RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / PTRDNAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +PTRDNAME A <domain-name> which points to some location in the + domain name space. + +PTR records cause no additional section processing. These RRs are used +in special domains to point to some other location in the domain space. +These records are simple data, and don't imply any special processing +similar to that performed by CNAME, which identifies aliases. See the +description of the IN-ADDR.ARPA domain for an example. + + + + + + + + +Mockapetris [Page 18] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.13. SOA RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / RNAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | SERIAL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | REFRESH | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RETRY | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | EXPIRE | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | MINIMUM | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MNAME The <domain-name> of the name server that was the + original or primary source of data for this zone. + +RNAME A <domain-name> which specifies the mailbox of the + person responsible for this zone. + +SERIAL The unsigned 32 bit version number of the original copy + of the zone. Zone transfers preserve this value. This + value wraps and should be compared using sequence space + arithmetic. + +REFRESH A 32 bit time interval before the zone should be + refreshed. + +RETRY A 32 bit time interval that should elapse before a + failed refresh should be retried. + +EXPIRE A 32 bit time value that specifies the upper limit on + the time interval that can elapse before the zone is no + longer authoritative. + + + + + +Mockapetris [Page 19] + +RFC 1035 Domain Implementation and Specification November 1987 + + +MINIMUM The unsigned 32 bit minimum TTL field that should be + exported with any RR from this zone. + +SOA records cause no additional section processing. + +All times are in units of seconds. + +Most of these fields are pertinent only for name server maintenance +operations. However, MINIMUM is used in all query operations that +retrieve RRs from a zone. Whenever a RR is sent in a response to a +query, the TTL field is set to the maximum of the TTL field from the RR +and the MINIMUM field in the appropriate SOA. Thus MINIMUM is a lower +bound on the TTL field for all RRs in a zone. Note that this use of +MINIMUM should occur when the RRs are copied into the response and not +when the zone is loaded from a master file or via a zone transfer. The +reason for this provison is to allow future dynamic update facilities to +change the SOA RR with known semantics. + + +3.3.14. TXT RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / TXT-DATA / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +TXT-DATA One or more <character-string>s. + +TXT RRs are used to hold descriptive text. The semantics of the text +depends on the domain where it is found. + +3.4. Internet specific RRs + +3.4.1. A RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ADDRESS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ADDRESS A 32 bit Internet address. + +Hosts that have multiple Internet addresses will have multiple A +records. + + + + + +Mockapetris [Page 20] + +RFC 1035 Domain Implementation and Specification November 1987 + + +A records cause no additional section processing. The RDATA section of +an A line in a master file is an Internet address expressed as four +decimal numbers separated by dots without any imbedded spaces (e.g., +"10.2.0.52" or "192.0.5.6"). + +3.4.2. WKS RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ADDRESS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | PROTOCOL | | + +--+--+--+--+--+--+--+--+ | + | | + / <BIT MAP> / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ADDRESS An 32 bit Internet address + +PROTOCOL An 8 bit IP protocol number + +<BIT MAP> A variable length bit map. The bit map must be a + multiple of 8 bits long. + +The WKS record is used to describe the well known services supported by +a particular protocol on a particular internet address. The PROTOCOL +field specifies an IP protocol number, and the bit map has one bit per +port of the specified protocol. The first bit corresponds to port 0, +the second to port 1, etc. If the bit map does not include a bit for a +protocol of interest, that bit is assumed zero. The appropriate values +and mnemonics for ports and protocols are specified in [RFC-1010]. + +For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port +25 (SMTP). If this bit is set, a SMTP server should be listening on TCP +port 25; if zero, SMTP service is not supported on the specified +address. + +The purpose of WKS RRs is to provide availability information for +servers for TCP and UDP. If a server supports both TCP and UDP, or has +multiple Internet addresses, then multiple WKS RRs are used. + +WKS RRs cause no additional section processing. + +In master files, both ports and protocols are expressed using mnemonics +or decimal numbers. + + + + +Mockapetris [Page 21] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.5. IN-ADDR.ARPA domain + +The Internet uses a special domain to support gateway location and +Internet address to host mapping. Other classes may employ a similar +strategy in other domains. The intent of this domain is to provide a +guaranteed method to perform host address to host name mapping, and to +facilitate queries to locate all gateways on a particular network in the +Internet. + +Note that both of these services are similar to functions that could be +performed by inverse queries; the difference is that this part of the +domain name space is structured according to address, and hence can +guarantee that the appropriate data can be located without an exhaustive +search of the domain space. + +The domain begins at IN-ADDR.ARPA and has a substructure which follows +the Internet addressing structure. + +Domain names in the IN-ADDR.ARPA domain are defined to have up to four +labels in addition to the IN-ADDR.ARPA suffix. Each label represents +one octet of an Internet address, and is expressed as a character string +for a decimal value in the range 0-255 (with leading zeros omitted +except in the case of a zero octet which is represented by a single +zero). + +Host addresses are represented by domain names that have all four labels +specified. Thus data for Internet address 10.2.0.52 is located at +domain name 52.0.2.10.IN-ADDR.ARPA. The reversal, though awkward to +read, allows zones to be delegated which are exactly one network of +address space. For example, 10.IN-ADDR.ARPA can be a zone containing +data for the ARPANET, while 26.IN-ADDR.ARPA can be a separate zone for +MILNET. Address nodes are used to hold pointers to primary host names +in the normal domain space. + +Network numbers correspond to some non-terminal nodes at various depths +in the IN-ADDR.ARPA domain, since Internet network numbers are either 1, +2, or 3 octets. Network nodes are used to hold pointers to the primary +host names of gateways attached to that network. Since a gateway is, by +definition, on more than one network, it will typically have two or more +network nodes which point at it. Gateways will also have host level +pointers at their fully qualified addresses. + +Both the gateway pointers at network nodes and the normal host pointers +at full address nodes use the PTR RR to point back to the primary domain +names of the corresponding hosts. + +For example, the IN-ADDR.ARPA domain will contain information about the +ISI gateway between net 10 and 26, an MIT gateway from net 10 to MIT's + + + +Mockapetris [Page 22] + +RFC 1035 Domain Implementation and Specification November 1987 + + +net 18, and hosts A.ISI.EDU and MULTICS.MIT.EDU. Assuming that ISI +gateway has addresses 10.2.0.22 and 26.0.0.103, and a name MILNET- +GW.ISI.EDU, and the MIT gateway has addresses 10.0.0.77 and 18.10.0.4 +and a name GW.LCS.MIT.EDU, the domain database would contain: + + 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 22.0.2.10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 103.0.0.26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 77.0.0.10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 4.0.10.18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 103.0.3.26.IN-ADDR.ARPA. PTR A.ISI.EDU. + 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU. + +Thus a program which wanted to locate gateways on net 10 would originate +a query of the form QTYPE=PTR, QCLASS=IN, QNAME=10.IN-ADDR.ARPA. It +would receive two RRs in response: + + 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + +The program could then originate QTYPE=A, QCLASS=IN queries for MILNET- +GW.ISI.EDU. and GW.LCS.MIT.EDU. to discover the Internet addresses of +these gateways. + +A resolver which wanted to find the host name corresponding to Internet +host address 10.0.0.6 would pursue a query of the form QTYPE=PTR, +QCLASS=IN, QNAME=6.0.0.10.IN-ADDR.ARPA, and would receive: + + 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU. + +Several cautions apply to the use of these services: + - Since the IN-ADDR.ARPA special domain and the normal domain + for a particular host or gateway will be in different zones, + the possibility exists that that the data may be inconsistent. + + - Gateways will often have two names in separate domains, only + one of which can be primary. + + - Systems that use the domain database to initialize their + routing tables must start with enough gateway information to + guarantee that they can access the appropriate name server. + + - The gateway data only reflects the existence of a gateway in a + manner equivalent to the current HOSTS.TXT file. It doesn't + replace the dynamic availability information from GGP or EGP. + + + +Mockapetris [Page 23] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.6. Defining new types, classes, and special namespaces + +The previously defined types and classes are the ones in use as of the +date of this memo. New definitions should be expected. This section +makes some recommendations to designers considering additions to the +existing facilities. The mailing list NAMEDROPPERS@SRI-NIC.ARPA is the +forum where general discussion of design issues takes place. + +In general, a new type is appropriate when new information is to be +added to the database about an existing object, or we need new data +formats for some totally new object. Designers should attempt to define +types and their RDATA formats that are generally applicable to all +classes, and which avoid duplication of information. New classes are +appropriate when the DNS is to be used for a new protocol, etc which +requires new class-specific data formats, or when a copy of the existing +name space is desired, but a separate management domain is necessary. + +New types and classes need mnemonics for master files; the format of the +master files requires that the mnemonics for type and class be disjoint. + +TYPE and CLASS values must be a proper subset of QTYPEs and QCLASSes +respectively. + +The present system uses multiple RRs to represent multiple values of a +type rather than storing multiple values in the RDATA section of a +single RR. This is less efficient for most applications, but does keep +RRs shorter. The multiple RRs assumption is incorporated in some +experimental work on dynamic update methods. + +The present system attempts to minimize the duplication of data in the +database in order to insure consistency. Thus, in order to find the +address of the host for a mail exchange, you map the mail domain name to +a host name, then the host name to addresses, rather than a direct +mapping to host address. This approach is preferred because it avoids +the opportunity for inconsistency. + +In defining a new type of data, multiple RR types should not be used to +create an ordering between entries or express different formats for +equivalent bindings, instead this information should be carried in the +body of the RR and a single type used. This policy avoids problems with +caching multiple types and defining QTYPEs to match multiple types. + +For example, the original form of mail exchange binding used two RR +types one to represent a "closer" exchange (MD) and one to represent a +"less close" exchange (MF). The difficulty is that the presence of one +RR type in a cache doesn't convey any information about the other +because the query which acquired the cached information might have used +a QTYPE of MF, MD, or MAILA (which matched both). The redesigned + + + +Mockapetris [Page 24] + +RFC 1035 Domain Implementation and Specification November 1987 + + +service used a single type (MX) with a "preference" value in the RDATA +section which can order different RRs. However, if any MX RRs are found +in the cache, then all should be there. + +4. MESSAGES + +4.1. Format + +All communications inside of the domain protocol are carried in a single +format called a message. The top level format of message is divided +into 5 sections (some of which are empty in certain cases) shown below: + + +---------------------+ + | Header | + +---------------------+ + | Question | the question for the name server + +---------------------+ + | Answer | RRs answering the question + +---------------------+ + | Authority | RRs pointing toward an authority + +---------------------+ + | Additional | RRs holding additional information + +---------------------+ + +The header section is always present. The header includes fields that +specify which of the remaining sections are present, and also specify +whether the message is a query or a response, a standard query or some +other opcode, etc. + +The names of the sections after the header are derived from their use in +standard queries. The question section contains fields that describe a +question to a name server. These fields are a query type (QTYPE), a +query class (QCLASS), and a query domain name (QNAME). The last three +sections have the same format: a possibly empty list of concatenated +resource records (RRs). The answer section contains RRs that answer the +question; the authority section contains RRs that point toward an +authoritative name server; the additional records section contains RRs +which relate to the query, but are not strictly answers for the +question. + + + + + + + + + + + + +Mockapetris [Page 25] + +RFC 1035 Domain Implementation and Specification November 1987 + + +4.1.1. Header section format + +The header contains the following fields: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ID | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QDCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ANCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | NSCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ARCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ID A 16 bit identifier assigned by the program that + generates any kind of query. This identifier is copied + the corresponding reply and can be used by the requester + to match up replies to outstanding queries. + +QR A one bit field that specifies whether this message is a + query (0), or a response (1). + +OPCODE A four bit field that specifies kind of query in this + message. This value is set by the originator of a query + and copied into the response. The values are: + + 0 a standard query (QUERY) + + 1 an inverse query (IQUERY) + + 2 a server status request (STATUS) + + 3-15 reserved for future use + +AA Authoritative Answer - this bit is valid in responses, + and specifies that the responding name server is an + authority for the domain name in question section. + + Note that the contents of the answer section may have + multiple owner names because of aliases. The AA bit + + + +Mockapetris [Page 26] + +RFC 1035 Domain Implementation and Specification November 1987 + + + corresponds to the name which matches the query name, or + the first owner name in the answer section. + +TC TrunCation - specifies that this message was truncated + due to length greater than that permitted on the + transmission channel. + +RD Recursion Desired - this bit may be set in a query and + is copied into the response. If RD is set, it directs + the name server to pursue the query recursively. + Recursive query support is optional. + +RA Recursion Available - this be is set or cleared in a + response, and denotes whether recursive query support is + available in the name server. + +Z Reserved for future use. Must be zero in all queries + and responses. + +RCODE Response code - this 4 bit field is set as part of + responses. The values have the following + interpretation: + + 0 No error condition + + 1 Format error - The name server was + unable to interpret the query. + + 2 Server failure - The name server was + unable to process this query due to a + problem with the name server. + + 3 Name Error - Meaningful only for + responses from an authoritative name + server, this code signifies that the + domain name referenced in the query does + not exist. + + 4 Not Implemented - The name server does + not support the requested kind of query. + + 5 Refused - The name server refuses to + perform the specified operation for + policy reasons. For example, a name + server may not wish to provide the + information to the particular requester, + or a name server may not wish to perform + a particular operation (e.g., zone + + + +Mockapetris [Page 27] + +RFC 1035 Domain Implementation and Specification November 1987 + + + transfer) for particular data. + + 6-15 Reserved for future use. + +QDCOUNT an unsigned 16 bit integer specifying the number of + entries in the question section. + +ANCOUNT an unsigned 16 bit integer specifying the number of + resource records in the answer section. + +NSCOUNT an unsigned 16 bit integer specifying the number of name + server resource records in the authority records + section. + +ARCOUNT an unsigned 16 bit integer specifying the number of + resource records in the additional records section. + +4.1.2. Question section format + +The question section is used to carry the "question" in most queries, +i.e., the parameters that define what is being asked. The section +contains QDCOUNT (usually 1) entries, each of the following format: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / QNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QTYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QCLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +QNAME a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used. + +QTYPE a two octet code which specifies the type of the query. + The values for this field include all codes valid for a + TYPE field, together with some more general codes which + can match more than one type of RR. + + + +Mockapetris [Page 28] + +RFC 1035 Domain Implementation and Specification November 1987 + + +QCLASS a two octet code that specifies the class of the query. + For example, the QCLASS field is IN for the Internet. + +4.1.3. Resource record format + +The answer, authority, and additional sections all share the same +format: a variable number of resource records, where the number of +records is specified in the corresponding count field in the header. +Each resource record has the following format: + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NAME a domain name to which this resource record pertains. + +TYPE two octets containing one of the RR type codes. This + field specifies the meaning of the data in the RDATA + field. + +CLASS two octets which specify the class of the data in the + RDATA field. + +TTL a 32 bit unsigned integer that specifies the time + interval (in seconds) that the resource record may be + cached before it should be discarded. Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached. + + + + + +Mockapetris [Page 29] + +RFC 1035 Domain Implementation and Specification November 1987 + + +RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + +RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + For example, the if the TYPE is A and the CLASS is IN, + the RDATA field is a 4 octet ARPA Internet address. + +4.1.4. Message compression + +In order to reduce the size of messages, the domain system utilizes a +compression scheme which eliminates the repetition of domain names in a +message. In this scheme, an entire domain name or a list of labels at +the end of a domain name is replaced with a pointer to a prior occurance +of the same name. + +The pointer takes the form of a two octet sequence: + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1| OFFSET | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +The first two bits are ones. This allows a pointer to be distinguished +from a label, since the label must begin with two zero bits because +labels are restricted to 63 octets or less. (The 10 and 01 combinations +are reserved for future use.) The OFFSET field specifies an offset from +the start of the message (i.e., the first octet of the ID field in the +domain header). A zero offset specifies the first byte of the ID field, +etc. + +The compression scheme allows a domain name in a message to be +represented as either: + + - a sequence of labels ending in a zero octet + + - a pointer + + - a sequence of labels ending with a pointer + +Pointers can only be used for occurances of a domain name where the +format is not class specific. If this were not the case, a name server +or resolver would be required to know the format of all RRs it handled. +As yet, there are no such cases, but they may occur in future RDATA +formats. + +If a domain name is contained in a part of the message subject to a +length field (such as the RDATA section of an RR), and compression is + + + +Mockapetris [Page 30] + +RFC 1035 Domain Implementation and Specification November 1987 + + +used, the length of the compressed name is used in the length +calculation, rather than the length of the expanded name. + +Programs are free to avoid using pointers in messages they generate, +although this will reduce datagram capacity, and may cause truncation. +However all programs are required to understand arriving messages that +contain pointers. + +For example, a datagram might need to use the domain names F.ISI.ARPA, +FOO.F.ISI.ARPA, ARPA, and the root. Ignoring the other fields of the +message, these domain names might be represented as: + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 20 | 1 | F | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 22 | 3 | I | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 24 | S | I | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 26 | 4 | A | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 28 | R | P | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 30 | A | 0 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 40 | 3 | F | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 42 | O | O | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 44 | 1 1| 20 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 64 | 1 1| 26 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 92 | 0 | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +The domain name for F.ISI.ARPA is shown at offset 20. The domain name +FOO.F.ISI.ARPA is shown at offset 40; this definition uses a pointer to +concatenate a label for FOO to the previously defined F.ISI.ARPA. The +domain name ARPA is defined at offset 64 using a pointer to the ARPA +component of the name F.ISI.ARPA at 20; note that this pointer relies on +ARPA being the last label in the string at 20. The root domain name is + + + +Mockapetris [Page 31] + +RFC 1035 Domain Implementation and Specification November 1987 + + +defined by a single octet of zeros at 92; the root domain name has no +labels. + +4.2. Transport + +The DNS assumes that messages will be transmitted as datagrams or in a +byte stream carried by a virtual circuit. While virtual circuits can be +used for any DNS activity, datagrams are preferred for queries due to +their lower overhead and better performance. Zone refresh activities +must use virtual circuits because of the need for reliable transfer. + +The Internet supports name server access using TCP [RFC-793] on server +port 53 (decimal) as well as datagram access using UDP [RFC-768] on UDP +port 53 (decimal). + +4.2.1. UDP usage + +Messages sent using UDP user server port 53 (decimal). + +Messages carried by UDP are restricted to 512 bytes (not counting the IP +or UDP headers). Longer messages are truncated and the TC bit is set in +the header. + +UDP is not acceptable for zone transfers, but is the recommended method +for standard queries in the Internet. Queries sent using UDP may be +lost, and hence a retransmission strategy is required. Queries or their +responses may be reordered by the network, or by processing in name +servers, so resolvers should not depend on them being returned in order. + +The optimal UDP retransmission policy will vary with performance of the +Internet and the needs of the client, but the following are recommended: + + - The client should try other servers and server addresses + before repeating a query to a specific address of a server. + + - The retransmission interval should be based on prior + statistics if possible. Too aggressive retransmission can + easily slow responses for the community at large. Depending + on how well connected the client is to its expected servers, + the minimum retransmission interval should be 2-5 seconds. + +More suggestions on server selection and retransmission policy can be +found in the resolver section of this memo. + +4.2.2. TCP usage + +Messages sent over TCP connections use server port 53 (decimal). The +message is prefixed with a two byte length field which gives the message + + + +Mockapetris [Page 32] + +RFC 1035 Domain Implementation and Specification November 1987 + + +length, excluding the two byte length field. This length field allows +the low-level processing to assemble a complete message before beginning +to parse it. + +Several connection management policies are recommended: + + - The server should not block other activities waiting for TCP + data. + + - The server should support multiple connections. + + - The server should assume that the client will initiate + connection closing, and should delay closing its end of the + connection until all outstanding client requests have been + satisfied. + + - If the server needs to close a dormant connection to reclaim + resources, it should wait until the connection has been idle + for a period on the order of two minutes. In particular, the + server should allow the SOA and AXFR request sequence (which + begins a refresh operation) to be made on a single connection. + Since the server would be unable to answer queries anyway, a + unilateral close or reset may be used instead of a graceful + close. + +5. MASTER FILES + +Master files are text files that contain RRs in text form. Since the +contents of a zone can be expressed in the form of a list of RRs a +master file is most often used to define a zone, though it can be used +to list a cache's contents. Hence, this section first discusses the +format of RRs in a master file, and then the special considerations when +a master file is used to create a zone in some name server. + +5.1. Format + +The format of these files is a sequence of entries. Entries are +predominantly line-oriented, though parentheses can be used to continue +a list of items across a line boundary, and text literals can contain +CRLF within the text. Any combination of tabs and spaces act as a +delimiter between the separate items that make up an entry. The end of +any line in the master file can end with a comment. The comment starts +with a ";" (semicolon). + +The following entries are defined: + + <blank>[<comment>] + + + + +Mockapetris [Page 33] + +RFC 1035 Domain Implementation and Specification November 1987 + + + $ORIGIN <domain-name> [<comment>] + + $INCLUDE <file-name> [<domain-name>] [<comment>] + + <domain-name><rr> [<comment>] + + <blank><rr> [<comment>] + +Blank lines, with or without comments, are allowed anywhere in the file. + +Two control entries are defined: $ORIGIN and $INCLUDE. $ORIGIN is +followed by a domain name, and resets the current origin for relative +domain names to the stated name. $INCLUDE inserts the named file into +the current file, and may optionally specify a domain name that sets the +relative domain name origin for the included file. $INCLUDE may also +have a comment. Note that a $INCLUDE entry never changes the relative +origin of the parent file, regardless of changes to the relative origin +made within the included file. + +The last two forms represent RRs. If an entry for an RR begins with a +blank, then the RR is assumed to be owned by the last stated owner. If +an RR entry begins with a <domain-name>, then the owner name is reset. + +<rr> contents take one of the following forms: + + [<TTL>] [<class>] <type> <RDATA> + + [<class>] [<TTL>] <type> <RDATA> + +The RR begins with optional TTL and class fields, followed by a type and +RDATA field appropriate to the type and class. Class and type use the +standard mnemonics, TTL is a decimal integer. Omitted class and TTL +values are default to the last explicitly stated values. Since type and +class mnemonics are disjoint, the parse is unique. (Note that this +order is different from the order used in examples and the order used in +the actual RRs; the given order allows easier parsing and defaulting.) + +<domain-name>s make up a large share of the data in the master file. +The labels in the domain name are expressed as character strings and +separated by dots. Quoting conventions allow arbitrary characters to be +stored in domain names. Domain names that end in a dot are called +absolute, and are taken as complete. Domain names which do not end in a +dot are called relative; the actual domain name is the concatenation of +the relative part with an origin specified in a $ORIGIN, $INCLUDE, or as +an argument to the master file loading routine. A relative name is an +error when no origin is available. + + + + + +Mockapetris [Page 34] + +RFC 1035 Domain Implementation and Specification November 1987 + + +<character-string> is expressed in one or two ways: as a contiguous set +of characters without interior spaces, or as a string beginning with a " +and ending with a ". Inside a " delimited string any character can +occur, except for a " itself, which must be quoted using \ (back slash). + +Because these files are text files several special encodings are +necessary to allow arbitrary data to be loaded. In particular: + + of the root. + +@ A free standing @ is used to denote the current origin. + +\X where X is any character other than a digit (0-9), is + used to quote that character so that its special meaning + does not apply. For example, "\." can be used to place + a dot character in a label. + +\DDD where each D is a digit is the octet corresponding to + the decimal number described by DDD. The resulting + octet is assumed to be text and is not checked for + special meaning. + +( ) Parentheses are used to group data that crosses a line + boundary. In effect, line terminations are not + recognized within parentheses. + +; Semicolon is used to start a comment; the remainder of + the line is ignored. + +5.2. Use of master files to define zones + +When a master file is used to load a zone, the operation should be +suppressed if any errors are encountered in the master file. The +rationale for this is that a single error can have widespread +consequences. For example, suppose that the RRs defining a delegation +have syntax errors; then the server will return authoritative name +errors for all names in the subzone (except in the case where the +subzone is also present on the server). + +Several other validity checks that should be performed in addition to +insuring that the file is syntactically correct: + + 1. All RRs in the file should have the same class. + + 2. Exactly one SOA RR should be present at the top of the zone. + + 3. If delegations are present and glue information is required, + it should be present. + + + +Mockapetris [Page 35] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 4. Information present outside of the authoritative nodes in the + zone should be glue information, rather than the result of an + origin or similar error. + +5.3. Master file example + +The following is an example file which might be used to define the +ISI.EDU zone.and is loaded with an origin of ISI.EDU: + +@ IN SOA VENERA Action\.domains ( + 20 ; SERIAL + 7200 ; REFRESH + 600 ; RETRY + 3600000; EXPIRE + 60) ; MINIMUM + + NS A.ISI.EDU. + NS VENERA + NS VAXA + MX 10 VENERA + MX 20 VAXA + +A A 26.3.0.103 + +VENERA A 10.1.0.52 + A 128.9.0.32 + +VAXA A 10.2.0.27 + A 128.9.0.33 + + +$INCLUDE <SUBSYS>ISI-MAILBOXES.TXT + +Where the file <SUBSYS>ISI-MAILBOXES.TXT is: + + MOE MB A.ISI.EDU. + LARRY MB A.ISI.EDU. + CURLEY MB A.ISI.EDU. + STOOGES MG MOE + MG LARRY + MG CURLEY + +Note the use of the \ character in the SOA RR to specify the responsible +person mailbox "Action.domains@E.ISI.EDU". + + + + + + + +Mockapetris [Page 36] + +RFC 1035 Domain Implementation and Specification November 1987 + + +6. NAME SERVER IMPLEMENTATION + +6.1. Architecture + +The optimal structure for the name server will depend on the host +operating system and whether the name server is integrated with resolver +operations, either by supporting recursive service, or by sharing its +database with a resolver. This section discusses implementation +considerations for a name server which shares a database with a +resolver, but most of these concerns are present in any name server. + +6.1.1. Control + +A name server must employ multiple concurrent activities, whether they +are implemented as separate tasks in the host's OS or multiplexing +inside a single name server program. It is simply not acceptable for a +name server to block the service of UDP requests while it waits for TCP +data for refreshing or query activities. Similarly, a name server +should not attempt to provide recursive service without processing such +requests in parallel, though it may choose to serialize requests from a +single client, or to regard identical requests from the same client as +duplicates. A name server should not substantially delay requests while +it reloads a zone from master files or while it incorporates a newly +refreshed zone into its database. + +6.1.2. Database + +While name server implementations are free to use any internal data +structures they choose, the suggested structure consists of three major +parts: + + - A "catalog" data structure which lists the zones available to + this server, and a "pointer" to the zone data structure. The + main purpose of this structure is to find the nearest ancestor + zone, if any, for arriving standard queries. + + - Separate data structures for each of the zones held by the + name server. + + - A data structure for cached data. (or perhaps separate caches + for different classes) + +All of these data structures can be implemented an identical tree +structure format, with different data chained off the nodes in different +parts: in the catalog the data is pointers to zones, while in the zone +and cache data structures, the data will be RRs. In designing the tree +framework the designer should recognize that query processing will need +to traverse the tree using case-insensitive label comparisons; and that + + + +Mockapetris [Page 37] + +RFC 1035 Domain Implementation and Specification November 1987 + + +in real data, a few nodes have a very high branching factor (100-1000 or +more), but the vast majority have a very low branching factor (0-1). + +One way to solve the case problem is to store the labels for each node +in two pieces: a standardized-case representation of the label where all +ASCII characters are in a single case, together with a bit mask that +denotes which characters are actually of a different case. The +branching factor diversity can be handled using a simple linked list for +a node until the branching factor exceeds some threshold, and +transitioning to a hash structure after the threshold is exceeded. In +any case, hash structures used to store tree sections must insure that +hash functions and procedures preserve the casing conventions of the +DNS. + +The use of separate structures for the different parts of the database +is motivated by several factors: + + - The catalog structure can be an almost static structure that + need change only when the system administrator changes the + zones supported by the server. This structure can also be + used to store parameters used to control refreshing + activities. + + - The individual data structures for zones allow a zone to be + replaced simply by changing a pointer in the catalog. Zone + refresh operations can build a new structure and, when + complete, splice it into the database via a simple pointer + replacement. It is very important that when a zone is + refreshed, queries should not use old and new data + simultaneously. + + - With the proper search procedures, authoritative data in zones + will always "hide", and hence take precedence over, cached + data. + + - Errors in zone definitions that cause overlapping zones, etc., + may cause erroneous responses to queries, but problem + determination is simplified, and the contents of one "bad" + zone can't corrupt another. + + - Since the cache is most frequently updated, it is most + vulnerable to corruption during system restarts. It can also + become full of expired RR data. In either case, it can easily + be discarded without disturbing zone data. + +A major aspect of database design is selecting a structure which allows +the name server to deal with crashes of the name server's host. State +information which a name server should save across system crashes + + + +Mockapetris [Page 38] + +RFC 1035 Domain Implementation and Specification November 1987 + + +includes the catalog structure (including the state of refreshing for +each zone) and the zone data itself. + +6.1.3. Time + +Both the TTL data for RRs and the timing data for refreshing activities +depends on 32 bit timers in units of seconds. Inside the database, +refresh timers and TTLs for cached data conceptually "count down", while +data in the zone stays with constant TTLs. + +A recommended implementation strategy is to store time in two ways: as +a relative increment and as an absolute time. One way to do this is to +use positive 32 bit numbers for one type and negative numbers for the +other. The RRs in zones use relative times; the refresh timers and +cache data use absolute times. Absolute numbers are taken with respect +to some known origin and converted to relative values when placed in the +response to a query. When an absolute TTL is negative after conversion +to relative, then the data is expired and should be ignored. + +6.2. Standard query processing + +The major algorithm for standard query processing is presented in +[RFC-1034]. + +When processing queries with QCLASS=*, or some other QCLASS which +matches multiple classes, the response should never be authoritative +unless the server can guarantee that the response covers all classes. + +When composing a response, RRs which are to be inserted in the +additional section, but duplicate RRs in the answer or authority +sections, may be omitted from the additional section. + +When a response is so long that truncation is required, the truncation +should start at the end of the response and work forward in the +datagram. Thus if there is any data for the authority section, the +answer section is guaranteed to be unique. + +The MINIMUM value in the SOA should be used to set a floor on the TTL of +data distributed from a zone. This floor function should be done when +the data is copied into a response. This will allow future dynamic +update protocols to change the SOA MINIMUM field without ambiguous +semantics. + +6.3. Zone refresh and reload processing + +In spite of a server's best efforts, it may be unable to load zone data +from a master file due to syntax errors, etc., or be unable to refresh a +zone within the its expiration parameter. In this case, the name server + + + +Mockapetris [Page 39] + +RFC 1035 Domain Implementation and Specification November 1987 + + +should answer queries as if it were not supposed to possess the zone. + +If a master is sending a zone out via AXFR, and a new version is created +during the transfer, the master should continue to send the old version +if possible. In any case, it should never send part of one version and +part of another. If completion is not possible, the master should reset +the connection on which the zone transfer is taking place. + +6.4. Inverse queries (Optional) + +Inverse queries are an optional part of the DNS. Name servers are not +required to support any form of inverse queries. If a name server +receives an inverse query that it does not support, it returns an error +response with the "Not Implemented" error set in the header. While +inverse query support is optional, all name servers must be at least +able to return the error response. + +6.4.1. The contents of inverse queries and responses Inverse +queries reverse the mappings performed by standard query operations; +while a standard query maps a domain name to a resource, an inverse +query maps a resource to a domain name. For example, a standard query +might bind a domain name to a host address; the corresponding inverse +query binds the host address to a domain name. + +Inverse queries take the form of a single RR in the answer section of +the message, with an empty question section. The owner name of the +query RR and its TTL are not significant. The response carries +questions in the question section which identify all names possessing +the query RR WHICH THE NAME SERVER KNOWS. Since no name server knows +about all of the domain name space, the response can never be assumed to +be complete. Thus inverse queries are primarily useful for database +management and debugging activities. Inverse queries are NOT an +acceptable method of mapping host addresses to host names; use the IN- +ADDR.ARPA domain instead. + +Where possible, name servers should provide case-insensitive comparisons +for inverse queries. Thus an inverse query asking for an MX RR of +"Venera.isi.edu" should get the same response as a query for +"VENERA.ISI.EDU"; an inverse query for HINFO RR "IBM-PC UNIX" should +produce the same result as an inverse query for "IBM-pc unix". However, +this cannot be guaranteed because name servers may possess RRs that +contain character strings but the name server does not know that the +data is character. + +When a name server processes an inverse query, it either returns: + + 1. zero, one, or multiple domain names for the specified + resource as QNAMEs in the question section + + + +Mockapetris [Page 40] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 2. an error code indicating that the name server doesn't support + inverse mapping of the specified resource type. + +When the response to an inverse query contains one or more QNAMEs, the +owner name and TTL of the RR in the answer section which defines the +inverse query is modified to exactly match an RR found at the first +QNAME. + +RRs returned in the inverse queries cannot be cached using the same +mechanism as is used for the replies to standard queries. One reason +for this is that a name might have multiple RRs of the same type, and +only one would appear. For example, an inverse query for a single +address of a multiply homed host might create the impression that only +one address existed. + +6.4.2. Inverse query and response example The overall structure +of an inverse query for retrieving the domain name that corresponds to +Internet address 10.1.0.52 is shown below: + + +-----------------------------------------+ + Header | OPCODE=IQUERY, ID=997 | + +-----------------------------------------+ + Question | <empty> | + +-----------------------------------------+ + Answer | <anyname> A IN 10.1.0.52 | + +-----------------------------------------+ + Authority | <empty> | + +-----------------------------------------+ + Additional | <empty> | + +-----------------------------------------+ + +This query asks for a question whose answer is the Internet style +address 10.1.0.52. Since the owner name is not known, any domain name +can be used as a placeholder (and is ignored). A single octet of zero, +signifying the root, is usually used because it minimizes the length of +the message. The TTL of the RR is not significant. The response to +this query might be: + + + + + + + + + + + + + + +Mockapetris [Page 41] + +RFC 1035 Domain Implementation and Specification November 1987 + + + +-----------------------------------------+ + Header | OPCODE=RESPONSE, ID=997 | + +-----------------------------------------+ + Question |QTYPE=A, QCLASS=IN, QNAME=VENERA.ISI.EDU | + +-----------------------------------------+ + Answer | VENERA.ISI.EDU A IN 10.1.0.52 | + +-----------------------------------------+ + Authority | <empty> | + +-----------------------------------------+ + Additional | <empty> | + +-----------------------------------------+ + +Note that the QTYPE in a response to an inverse query is the same as the +TYPE field in the answer section of the inverse query. Responses to +inverse queries may contain multiple questions when the inverse is not +unique. If the question section in the response is not empty, then the +RR in the answer section is modified to correspond to be an exact copy +of an RR at the first QNAME. + +6.4.3. Inverse query processing + +Name servers that support inverse queries can support these operations +through exhaustive searches of their databases, but this becomes +impractical as the size of the database increases. An alternative +approach is to invert the database according to the search key. + +For name servers that support multiple zones and a large amount of data, +the recommended approach is separate inversions for each zone. When a +particular zone is changed during a refresh, only its inversions need to +be redone. + +Support for transfer of this type of inversion may be included in future +versions of the domain system, but is not supported in this version. + +6.5. Completion queries and responses + +The optional completion services described in RFC-882 and RFC-883 have +been deleted. Redesigned services may become available in the future. + + + + + + + + + + + + + +Mockapetris [Page 42] + +RFC 1035 Domain Implementation and Specification November 1987 + + +7. RESOLVER IMPLEMENTATION + +The top levels of the recommended resolver algorithm are discussed in +[RFC-1034]. This section discusses implementation details assuming the +database structure suggested in the name server implementation section +of this memo. + +7.1. Transforming a user request into a query + +The first step a resolver takes is to transform the client's request, +stated in a format suitable to the local OS, into a search specification +for RRs at a specific name which match a specific QTYPE and QCLASS. +Where possible, the QTYPE and QCLASS should correspond to a single type +and a single class, because this makes the use of cached data much +simpler. The reason for this is that the presence of data of one type +in a cache doesn't confirm the existence or non-existence of data of +other types, hence the only way to be sure is to consult an +authoritative source. If QCLASS=* is used, then authoritative answers +won't be available. + +Since a resolver must be able to multiplex multiple requests if it is to +perform its function efficiently, each pending request is usually +represented in some block of state information. This state block will +typically contain: + + - A timestamp indicating the time the request began. + The timestamp is used to decide whether RRs in the database + can be used or are out of date. This timestamp uses the + absolute time format previously discussed for RR storage in + zones and caches. Note that when an RRs TTL indicates a + relative time, the RR must be timely, since it is part of a + zone. When the RR has an absolute time, it is part of a + cache, and the TTL of the RR is compared against the timestamp + for the start of the request. + + Note that using the timestamp is superior to using a current + time, since it allows RRs with TTLs of zero to be entered in + the cache in the usual manner, but still used by the current + request, even after intervals of many seconds due to system + load, query retransmission timeouts, etc. + + - Some sort of parameters to limit the amount of work which will + be performed for this request. + + The amount of work which a resolver will do in response to a + client request must be limited to guard against errors in the + database, such as circular CNAME references, and operational + problems, such as network partition which prevents the + + + +Mockapetris [Page 43] + +RFC 1035 Domain Implementation and Specification November 1987 + + + resolver from accessing the name servers it needs. While + local limits on the number of times a resolver will retransmit + a particular query to a particular name server address are + essential, the resolver should have a global per-request + counter to limit work on a single request. The counter should + be set to some initial value and decremented whenever the + resolver performs any action (retransmission timeout, + retransmission, etc.) If the counter passes zero, the request + is terminated with a temporary error. + + Note that if the resolver structure allows one request to + start others in parallel, such as when the need to access a + name server for one request causes a parallel resolve for the + name server's addresses, the spawned request should be started + with a lower counter. This prevents circular references in + the database from starting a chain reaction of resolver + activity. + + - The SLIST data structure discussed in [RFC-1034]. + + This structure keeps track of the state of a request if it + must wait for answers from foreign name servers. + +7.2. Sending the queries + +As described in [RFC-1034], the basic task of the resolver is to +formulate a query which will answer the client's request and direct that +query to name servers which can provide the information. The resolver +will usually only have very strong hints about which servers to ask, in +the form of NS RRs, and may have to revise the query, in response to +CNAMEs, or revise the set of name servers the resolver is asking, in +response to delegation responses which point the resolver to name +servers closer to the desired information. In addition to the +information requested by the client, the resolver may have to call upon +its own services to determine the address of name servers it wishes to +contact. + +In any case, the model used in this memo assumes that the resolver is +multiplexing attention between multiple requests, some from the client, +and some internally generated. Each request is represented by some +state information, and the desired behavior is that the resolver +transmit queries to name servers in a way that maximizes the probability +that the request is answered, minimizes the time that the request takes, +and avoids excessive transmissions. The key algorithm uses the state +information of the request to select the next name server address to +query, and also computes a timeout which will cause the next action +should a response not arrive. The next action will usually be a +transmission to some other server, but may be a temporary error to the + + + +Mockapetris [Page 44] + +RFC 1035 Domain Implementation and Specification November 1987 + + +client. + +The resolver always starts with a list of server names to query (SLIST). +This list will be all NS RRs which correspond to the nearest ancestor +zone that the resolver knows about. To avoid startup problems, the +resolver should have a set of default servers which it will ask should +it have no current NS RRs which are appropriate. The resolver then adds +to SLIST all of the known addresses for the name servers, and may start +parallel requests to acquire the addresses of the servers when the +resolver has the name, but no addresses, for the name servers. + +To complete initialization of SLIST, the resolver attaches whatever +history information it has to the each address in SLIST. This will +usually consist of some sort of weighted averages for the response time +of the address, and the batting average of the address (i.e., how often +the address responded at all to the request). Note that this +information should be kept on a per address basis, rather than on a per +name server basis, because the response time and batting average of a +particular server may vary considerably from address to address. Note +also that this information is actually specific to a resolver address / +server address pair, so a resolver with multiple addresses may wish to +keep separate histories for each of its addresses. Part of this step +must deal with addresses which have no such history; in this case an +expected round trip time of 5-10 seconds should be the worst case, with +lower estimates for the same local network, etc. + +Note that whenever a delegation is followed, the resolver algorithm +reinitializes SLIST. + +The information establishes a partial ranking of the available name +server addresses. Each time an address is chosen and the state should +be altered to prevent its selection again until all other addresses have +been tried. The timeout for each transmission should be 50-100% greater +than the average predicted value to allow for variance in response. + +Some fine points: + + - The resolver may encounter a situation where no addresses are + available for any of the name servers named in SLIST, and + where the servers in the list are precisely those which would + normally be used to look up their own addresses. This + situation typically occurs when the glue address RRs have a + smaller TTL than the NS RRs marking delegation, or when the + resolver caches the result of a NS search. The resolver + should detect this condition and restart the search at the + next ancestor zone, or alternatively at the root. + + + + + +Mockapetris [Page 45] + +RFC 1035 Domain Implementation and Specification November 1987 + + + - If a resolver gets a server error or other bizarre response + from a name server, it should remove it from SLIST, and may + wish to schedule an immediate transmission to the next + candidate server address. + +7.3. Processing responses + +The first step in processing arriving response datagrams is to parse the +response. This procedure should include: + + - Check the header for reasonableness. Discard datagrams which + are queries when responses are expected. + + - Parse the sections of the message, and insure that all RRs are + correctly formatted. + + - As an optional step, check the TTLs of arriving data looking + for RRs with excessively long TTLs. If a RR has an + excessively long TTL, say greater than 1 week, either discard + the whole response, or limit all TTLs in the response to 1 + week. + +The next step is to match the response to a current resolver request. +The recommended strategy is to do a preliminary matching using the ID +field in the domain header, and then to verify that the question section +corresponds to the information currently desired. This requires that +the transmission algorithm devote several bits of the domain ID field to +a request identifier of some sort. This step has several fine points: + + - Some name servers send their responses from different + addresses than the one used to receive the query. That is, a + resolver cannot rely that a response will come from the same + address which it sent the corresponding query to. This name + server bug is typically encountered in UNIX systems. + + - If the resolver retransmits a particular request to a name + server it should be able to use a response from any of the + transmissions. However, if it is using the response to sample + the round trip time to access the name server, it must be able + to determine which transmission matches the response (and keep + transmission times for each outgoing message), or only + calculate round trip times based on initial transmissions. + + - A name server will occasionally not have a current copy of a + zone which it should have according to some NS RRs. The + resolver should simply remove the name server from the current + SLIST, and continue. + + + + +Mockapetris [Page 46] + +RFC 1035 Domain Implementation and Specification November 1987 + + +7.4. Using the cache + +In general, we expect a resolver to cache all data which it receives in +responses since it may be useful in answering future client requests. +However, there are several types of data which should not be cached: + + - When several RRs of the same type are available for a + particular owner name, the resolver should either cache them + all or none at all. When a response is truncated, and a + resolver doesn't know whether it has a complete set, it should + not cache a possibly partial set of RRs. + + - Cached data should never be used in preference to + authoritative data, so if caching would cause this to happen + the data should not be cached. + + - The results of an inverse query should not be cached. + + - The results of standard queries where the QNAME contains "*" + labels if the data might be used to construct wildcards. The + reason is that the cache does not necessarily contain existing + RRs or zone boundary information which is necessary to + restrict the application of the wildcard RRs. + + - RR data in responses of dubious reliability. When a resolver + receives unsolicited responses or RR data other than that + requested, it should discard it without caching it. The basic + implication is that all sanity checks on a packet should be + performed before any of it is cached. + +In a similar vein, when a resolver has a set of RRs for some name in a +response, and wants to cache the RRs, it should check its cache for +already existing RRs. Depending on the circumstances, either the data +in the response or the cache is preferred, but the two should never be +combined. If the data in the response is from authoritative data in the +answer section, it is always preferred. + +8. MAIL SUPPORT + +The domain system defines a standard for mapping mailboxes into domain +names, and two methods for using the mailbox information to derive mail +routing information. The first method is called mail exchange binding +and the other method is mailbox binding. The mailbox encoding standard +and mail exchange binding are part of the DNS official protocol, and are +the recommended method for mail routing in the Internet. Mailbox +binding is an experimental feature which is still under development and +subject to change. + + + + +Mockapetris [Page 47] + +RFC 1035 Domain Implementation and Specification November 1987 + + +The mailbox encoding standard assumes a mailbox name of the form +"<local-part>@<mail-domain>". While the syntax allowed in each of these +sections varies substantially between the various mail internets, the +preferred syntax for the ARPA Internet is given in [RFC-822]. + +The DNS encodes the <local-part> as a single label, and encodes the +<mail-domain> as a domain name. The single label from the <local-part> +is prefaced to the domain name from <mail-domain> to form the domain +name corresponding to the mailbox. Thus the mailbox HOSTMASTER@SRI- +NIC.ARPA is mapped into the domain name HOSTMASTER.SRI-NIC.ARPA. If the +<local-part> contains dots or other special characters, its +representation in a master file will require the use of backslash +quoting to ensure that the domain name is properly encoded. For +example, the mailbox Action.domains@ISI.EDU would be represented as +Action\.domains.ISI.EDU. + +8.1. Mail exchange binding + +Mail exchange binding uses the <mail-domain> part of a mailbox +specification to determine where mail should be sent. The <local-part> +is not even consulted. [RFC-974] specifies this method in detail, and +should be consulted before attempting to use mail exchange support. + +One of the advantages of this method is that it decouples mail +destination naming from the hosts used to support mail service, at the +cost of another layer of indirection in the lookup function. However, +the addition layer should eliminate the need for complicated "%", "!", +etc encodings in <local-part>. + +The essence of the method is that the <mail-domain> is used as a domain +name to locate type MX RRs which list hosts willing to accept mail for +<mail-domain>, together with preference values which rank the hosts +according to an order specified by the administrators for <mail-domain>. + +In this memo, the <mail-domain> ISI.EDU is used in examples, together +with the hosts VENERA.ISI.EDU and VAXA.ISI.EDU as mail exchanges for +ISI.EDU. If a mailer had a message for Mockapetris@ISI.EDU, it would +route it by looking up MX RRs for ISI.EDU. The MX RRs at ISI.EDU name +VENERA.ISI.EDU and VAXA.ISI.EDU, and type A queries can find the host +addresses. + +8.2. Mailbox binding (Experimental) + +In mailbox binding, the mailer uses the entire mail destination +specification to construct a domain name. The encoded domain name for +the mailbox is used as the QNAME field in a QTYPE=MAILB query. + +Several outcomes are possible for this query: + + + +Mockapetris [Page 48] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 1. The query can return a name error indicating that the mailbox + does not exist as a domain name. + + In the long term, this would indicate that the specified + mailbox doesn't exist. However, until the use of mailbox + binding is universal, this error condition should be + interpreted to mean that the organization identified by the + global part does not support mailbox binding. The + appropriate procedure is to revert to exchange binding at + this point. + + 2. The query can return a Mail Rename (MR) RR. + + The MR RR carries new mailbox specification in its RDATA + field. The mailer should replace the old mailbox with the + new one and retry the operation. + + 3. The query can return a MB RR. + + The MB RR carries a domain name for a host in its RDATA + field. The mailer should deliver the message to that host + via whatever protocol is applicable, e.g., b,SMTP. + + 4. The query can return one or more Mail Group (MG) RRs. + + This condition means that the mailbox was actually a mailing + list or mail group, rather than a single mailbox. Each MG RR + has a RDATA field that identifies a mailbox that is a member + of the group. The mailer should deliver a copy of the + message to each member. + + 5. The query can return a MB RR as well as one or more MG RRs. + + This condition means the the mailbox was actually a mailing + list. The mailer can either deliver the message to the host + specified by the MB RR, which will in turn do the delivery to + all members, or the mailer can use the MG RRs to do the + expansion itself. + +In any of these cases, the response may include a Mail Information +(MINFO) RR. This RR is usually associated with a mail group, but is +legal with a MB. The MINFO RR identifies two mailboxes. One of these +identifies a responsible person for the original mailbox name. This +mailbox should be used for requests to be added to a mail group, etc. +The second mailbox name in the MINFO RR identifies a mailbox that should +receive error messages for mail failures. This is particularly +appropriate for mailing lists when errors in member names should be +reported to a person other than the one who sends a message to the list. + + + +Mockapetris [Page 49] + +RFC 1035 Domain Implementation and Specification November 1987 + + +New fields may be added to this RR in the future. + + +9. REFERENCES and BIBLIOGRAPHY + +[Dyer 87] S. Dyer, F. Hsu, "Hesiod", Project Athena + Technical Plan - Name Service, April 1987, version 1.9. + + Describes the fundamentals of the Hesiod name service. + +[IEN-116] J. Postel, "Internet Name Server", IEN-116, + USC/Information Sciences Institute, August 1979. + + A name service obsoleted by the Domain Name System, but + still in use. + +[Quarterman 86] J. Quarterman, and J. Hoskins, "Notable Computer Networks", + Communications of the ACM, October 1986, volume 29, number + 10. + +[RFC-742] K. Harrenstien, "NAME/FINGER", RFC-742, Network + Information Center, SRI International, December 1977. + +[RFC-768] J. Postel, "User Datagram Protocol", RFC-768, + USC/Information Sciences Institute, August 1980. + +[RFC-793] J. Postel, "Transmission Control Protocol", RFC-793, + USC/Information Sciences Institute, September 1981. + +[RFC-799] D. Mills, "Internet Name Domains", RFC-799, COMSAT, + September 1981. + + Suggests introduction of a hierarchy in place of a flat + name space for the Internet. + +[RFC-805] J. Postel, "Computer Mail Meeting Notes", RFC-805, + USC/Information Sciences Institute, February 1982. + +[RFC-810] E. Feinler, K. Harrenstien, Z. Su, and V. White, "DOD + Internet Host Table Specification", RFC-810, Network + Information Center, SRI International, March 1982. + + Obsolete. See RFC-952. + +[RFC-811] K. Harrenstien, V. White, and E. Feinler, "Hostnames + Server", RFC-811, Network Information Center, SRI + International, March 1982. + + + + +Mockapetris [Page 50] + +RFC 1035 Domain Implementation and Specification November 1987 + + + Obsolete. See RFC-953. + +[RFC-812] K. Harrenstien, and V. White, "NICNAME/WHOIS", RFC-812, + Network Information Center, SRI International, March + 1982. + +[RFC-819] Z. Su, and J. Postel, "The Domain Naming Convention for + Internet User Applications", RFC-819, Network + Information Center, SRI International, August 1982. + + Early thoughts on the design of the domain system. + Current implementation is completely different. + +[RFC-821] J. Postel, "Simple Mail Transfer Protocol", RFC-821, + USC/Information Sciences Institute, August 1980. + +[RFC-830] Z. Su, "A Distributed System for Internet Name Service", + RFC-830, Network Information Center, SRI International, + October 1982. + + Early thoughts on the design of the domain system. + Current implementation is completely different. + +[RFC-882] P. Mockapetris, "Domain names - Concepts and + Facilities," RFC-882, USC/Information Sciences + Institute, November 1983. + + Superceeded by this memo. + +[RFC-883] P. Mockapetris, "Domain names - Implementation and + Specification," RFC-883, USC/Information Sciences + Institute, November 1983. + + Superceeded by this memo. + +[RFC-920] J. Postel and J. Reynolds, "Domain Requirements", + RFC-920, USC/Information Sciences Institute, + October 1984. + + Explains the naming scheme for top level domains. + +[RFC-952] K. Harrenstien, M. Stahl, E. Feinler, "DoD Internet Host + Table Specification", RFC-952, SRI, October 1985. + + Specifies the format of HOSTS.TXT, the host/address + table replaced by the DNS. + + + + + +Mockapetris [Page 51] + +RFC 1035 Domain Implementation and Specification November 1987 + + +[RFC-953] K. Harrenstien, M. Stahl, E. Feinler, "HOSTNAME Server", + RFC-953, SRI, October 1985. + + This RFC contains the official specification of the + hostname server protocol, which is obsoleted by the DNS. + This TCP based protocol accesses information stored in + the RFC-952 format, and is used to obtain copies of the + host table. + +[RFC-973] P. Mockapetris, "Domain System Changes and + Observations", RFC-973, USC/Information Sciences + Institute, January 1986. + + Describes changes to RFC-882 and RFC-883 and reasons for + them. + +[RFC-974] C. Partridge, "Mail routing and the domain system", + RFC-974, CSNET CIC BBN Labs, January 1986. + + Describes the transition from HOSTS.TXT based mail + addressing to the more powerful MX system used with the + domain system. + +[RFC-1001] NetBIOS Working Group, "Protocol standard for a NetBIOS + service on a TCP/UDP transport: Concepts and Methods", + RFC-1001, March 1987. + + This RFC and RFC-1002 are a preliminary design for + NETBIOS on top of TCP/IP which proposes to base NetBIOS + name service on top of the DNS. + +[RFC-1002] NetBIOS Working Group, "Protocol standard for a NetBIOS + service on a TCP/UDP transport: Detailed + Specifications", RFC-1002, March 1987. + +[RFC-1010] J. Reynolds, and J. Postel, "Assigned Numbers", RFC-1010, + USC/Information Sciences Institute, May 1987. + + Contains socket numbers and mnemonics for host names, + operating systems, etc. + +[RFC-1031] W. Lazear, "MILNET Name Domain Transition", RFC-1031, + November 1987. + + Describes a plan for converting the MILNET to the DNS. + +[RFC-1032] M. Stahl, "Establishing a Domain - Guidelines for + Administrators", RFC-1032, November 1987. + + + +Mockapetris [Page 52] + +RFC 1035 Domain Implementation and Specification November 1987 + + + Describes the registration policies used by the NIC to + administer the top level domains and delegate subzones. + +[RFC-1033] M. Lottor, "Domain Administrators Operations Guide", + RFC-1033, November 1987. + + A cookbook for domain administrators. + +[Solomon 82] M. Solomon, L. Landweber, and D. Neuhengen, "The CSNET + Name Server", Computer Networks, vol 6, nr 3, July 1982. + + Describes a name service for CSNET which is independent + from the DNS and DNS use in the CSNET. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Mockapetris [Page 53] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Index + + * 13 + + ; 33, 35 + + <character-string> 35 + <domain-name> 34 + + @ 35 + + \ 35 + + A 12 + + Byte order 8 + + CH 13 + Character case 9 + CLASS 11 + CNAME 12 + Completion 42 + CS 13 + + Hesiod 13 + HINFO 12 + HS 13 + + IN 13 + IN-ADDR.ARPA domain 22 + Inverse queries 40 + + Mailbox names 47 + MB 12 + MD 12 + MF 12 + MG 12 + MINFO 12 + MINIMUM 20 + MR 12 + MX 12 + + NS 12 + NULL 12 + + Port numbers 32 + Primary server 5 + PTR 12, 18 + + + +Mockapetris [Page 54] + +RFC 1035 Domain Implementation and Specification November 1987 + + + QCLASS 13 + QTYPE 12 + + RDATA 12 + RDLENGTH 11 + + Secondary server 5 + SOA 12 + Stub resolvers 7 + + TCP 32 + TXT 12 + TYPE 11 + + UDP 32 + + WKS 12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Mockapetris [Page 55] + diff --git a/lib/dns/tests/testdata/master/master1.data b/lib/dns/tests/testdata/master/master1.data new file mode 100644 index 0000000..030bc68 --- /dev/null +++ b/lib/dns/tests/testdata/master/master1.data @@ -0,0 +1,11 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. +b in a 1.2.3.4 diff --git a/lib/dns/tests/testdata/master/master10.data b/lib/dns/tests/testdata/master/master10.data new file mode 100644 index 0000000..9ee052f --- /dev/null +++ b/lib/dns/tests/testdata/master/master10.data @@ -0,0 +1,7 @@ +; +; the following black line contains spaces + +; +@ 300 IN A 10.0.0.1 + ; +; diff --git a/lib/dns/tests/testdata/master/master11.data b/lib/dns/tests/testdata/master/master11.data new file mode 100644 index 0000000..0aaec25 --- /dev/null +++ b/lib/dns/tests/testdata/master/master11.data @@ -0,0 +1,6 @@ +; +; The following serial number contains a leading 0 and a 9 so the +; we can catch cases where it is incorrectly treated as a octal +; number. +; +@ 300 IN SOA ns hostmaster 00090000 1200 3600 604800 300 diff --git a/lib/dns/tests/testdata/master/master12.data.in b/lib/dns/tests/testdata/master/master12.data.in new file mode 100644 index 0000000..3634388 --- /dev/null +++ b/lib/dns/tests/testdata/master/master12.data.in @@ -0,0 +1 @@ +00000002000000004ed7306600000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/lib/dns/tests/testdata/master/master13.data.in b/lib/dns/tests/testdata/master/master13.data.in new file mode 100644 index 0000000..d1c262f --- /dev/null +++ b/lib/dns/tests/testdata/master/master13.data.in @@ -0,0 +1 @@ +00000002000000014ed7337f00000000000000000000000000000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/lib/dns/tests/testdata/master/master14.data.in b/lib/dns/tests/testdata/master/master14.data.in new file mode 100644 index 0000000..149a25f --- /dev/null +++ b/lib/dns/tests/testdata/master/master14.data.in @@ -0,0 +1 @@ +00000002000000014ed7337f0000000277df41e50000000000000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/lib/dns/tests/testdata/master/master15.data b/lib/dns/tests/testdata/master/master15.data new file mode 100644 index 0000000..cf413ce --- /dev/null +++ b/lib/dns/tests/testdata/master/master15.data @@ -0,0 +1,1609 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. +b in a 1.2.3.4 +c in txt ( TOOBIGTOOBIGTOOBIGTOOBIGTOOBIGTOOBI + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 ) diff --git a/lib/dns/tests/testdata/master/master16.data b/lib/dns/tests/testdata/master/master16.data new file mode 100644 index 0000000..e969bd3 --- /dev/null +++ b/lib/dns/tests/testdata/master/master16.data @@ -0,0 +1,1609 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. +b in a 1.2.3.4 +c in txt ( MAXSIZSEMAXSIZSEMAXSIZSEMAXSIZSMAX + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 ) diff --git a/lib/dns/tests/testdata/master/master17.data b/lib/dns/tests/testdata/master/master17.data new file mode 100644 index 0000000..4b2b63d --- /dev/null +++ b/lib/dns/tests/testdata/master/master17.data @@ -0,0 +1,14 @@ +$ORIGIN test. +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.test. + in ns ns2.test. + in ns ns3.test. +b in a 1.2.3.4 +$ORIGIN sub.test. + in a 4.3.2.1 diff --git a/lib/dns/tests/testdata/master/master18.data b/lib/dns/tests/testdata/master/master18.data new file mode 100644 index 0000000..dddf04e --- /dev/null +++ b/lib/dns/tests/testdata/master/master18.data @@ -0,0 +1,10 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + +$INCLUDE "testkeys/Kexample.+008+20386.key"; +$INCLUDE "testkeys/Kexample.+008+37464.key"; diff --git a/lib/dns/tests/testdata/master/master2.data b/lib/dns/tests/testdata/master/master2.data new file mode 100644 index 0000000..b8ca38d --- /dev/null +++ b/lib/dns/tests/testdata/master/master2.data @@ -0,0 +1,11 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum +a in ns +a in ns ns2vix.com. +a in ns ns3vix.com. +b in a 1.2.3.4 diff --git a/lib/dns/tests/testdata/master/master3.data b/lib/dns/tests/testdata/master/master3.data new file mode 100644 index 0000000..7283af6 --- /dev/null +++ b/lib/dns/tests/testdata/master/master3.data @@ -0,0 +1,11 @@ +$TTL 1000 + in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com + in ns ns2vix.com. +a in ns ns3vix.com. +b in a 1.2.3.4 diff --git a/lib/dns/tests/testdata/master/master4.data b/lib/dns/tests/testdata/master/master4.data new file mode 100644 index 0000000..3a694ea --- /dev/null +++ b/lib/dns/tests/testdata/master/master4.data @@ -0,0 +1,11 @@ + +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum +a in ns ns.vix.com. +a in ns ns2vix.com. +a in ns ns3vix.com. +b in a 1.2.3.4 diff --git a/lib/dns/tests/testdata/master/master5.data b/lib/dns/tests/testdata/master/master5.data new file mode 100644 index 0000000..95234bd --- /dev/null +++ b/lib/dns/tests/testdata/master/master5.data @@ -0,0 +1,11 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum +a any ns ns.vix.com. +a in ns ns2vix.com. +a in ns ns3vix.com. +b in a 1.2.3.4 diff --git a/lib/dns/tests/testdata/master/master6.data b/lib/dns/tests/testdata/master/master6.data new file mode 100644 index 0000000..a9a37bb --- /dev/null +++ b/lib/dns/tests/testdata/master/master6.data @@ -0,0 +1,33 @@ + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + +secure1 3600 IN DNSKEY ( + FLAG2|FLAG4|FLAG5|NTYP3|FLAG8|FLAG9|FLAG10|FLAG11|SIG15 + 3 3 + ArT0a8FtOZWEONG2YQVl9+RA34op30JPz4NPEroCxm2yImT2 + 2OYggnPIzrgayyepgKU1PfTTypnJDTwrSrtISyEsj7tjM7/n + 03DP8VWSn0aLwpUuc7Sx9vtM1Wi+YeiA4Bv2Oz1VB9de4qql + sIq+KLn8J4wz95bGnJ0mHUB7oTDJ3Hl1zeaCMdX69Kr46yAY + AvGJJdGGDYxYgxzx2zNdzypkYSkxpdsNqUt38tabSfdvCn12 + pnmSWjlVJsjHhsaYnrPhouN5acOXMNbxNVbGU5LZ8Es6EYbV + /7YMt8VUkA8/8UCszBBT7XAJ3OFjiMO8mvxrZZFzvwJlPBQ1 + oFq/TNZlSe+N ) + +secure2 3600 in DNSKEY ( + flag2|flag4|flag5|ntyp3|flag8|flag9|flag10|flag11|sig15 + 3 3 + ArT0a8FtOZWEONG2YQVl9+RA34op30JPz4NPEroCxm2yImT2 + 2OYggnPIzrgayyepgKU1PfTTypnJDTwrSrtISyEsj7tjM7/n + 03DP8VWSn0aLwpUuc7Sx9vtM1Wi+YeiA4Bv2Oz1VB9de4qql + sIq+KLn8J4wz95bGnJ0mHUB7oTDJ3Hl1zeaCMdX69Kr46yAY + AvGJJdGGDYxYgxzx2zNdzypkYSkxpdsNqUt38tabSfdvCn12 + pnmSWjlVJsjHhsaYnrPhouN5acOXMNbxNVbGU5LZ8Es6EYbV + /7YMt8VUkA8/8UCszBBT7XAJ3OFjiMO8mvxrZZFzvwJlPBQ1 + oFq/TNZlSe+N ) + diff --git a/lib/dns/tests/testdata/master/master7.data b/lib/dns/tests/testdata/master/master7.data new file mode 100644 index 0000000..2638b5d --- /dev/null +++ b/lib/dns/tests/testdata/master/master7.data @@ -0,0 +1,17 @@ + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + +secure1 3600 IN DNSKEY ( + NOKEY|FLAG2|FLAG4|FLAG5|NTYP3|FLAG8|FLAG9|FLAG10|FLAG11|SIG15 + 3 3 ) + +secure2 3600 in DNSKEY ( + nokey|flag2|flag4|flag5|ntyp3|flag8|flag9|flag10|flag11|sig15 + 3 3 ) + diff --git a/lib/dns/tests/testdata/master/master8.data b/lib/dns/tests/testdata/master/master8.data new file mode 100644 index 0000000..2210f42 --- /dev/null +++ b/lib/dns/tests/testdata/master/master8.data @@ -0,0 +1,4 @@ +; +; master7.data contains a good zone file +; +$include testdata/master/master7.data diff --git a/lib/dns/tests/testdata/master/master9.data b/lib/dns/tests/testdata/master/master9.data new file mode 100644 index 0000000..b22688b --- /dev/null +++ b/lib/dns/tests/testdata/master/master9.data @@ -0,0 +1,4 @@ +; +; master5.data is bad +; +$include testdata/master/master5.data diff --git a/lib/dns/tests/testdata/nsec3/1024.db b/lib/dns/tests/testdata/nsec3/1024.db new file mode 100644 index 0000000..2e7f182 --- /dev/null +++ b/lib/dns/tests/testdata/nsec3/1024.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 1024 bit key. +test. IN DNSKEY 256 3 5 AwEAAd5oKx06HRE6NRrTDz49lljdRmxgp/4YB/cyMkpwUMkaLhDNCfTq hql84ab2LRbtUWLHFXGWENvxPGQzVHeleXu+3ThNfFOwIaySedxHmLGT lTtBRDhPc8iSb+2IYDemmA+ut8kwHhCVz/tDMbD/dgAswdOtmXCpQyJk Q1HqY3Xj diff --git a/lib/dns/tests/testdata/nsec3/2048.db b/lib/dns/tests/testdata/nsec3/2048.db new file mode 100644 index 0000000..eed399a --- /dev/null +++ b/lib/dns/tests/testdata/nsec3/2048.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 2048 bits +test. IN DNSKEY 256 3 5 AwEAAcfQX59iZr9gK+XzhTZQ5KWrfCLA0iYHTqheEIhC2dXS8gUSppQS g9SmzH2129u/LSSb7gqJSoLLAsn36iinqCqUXl2BT6xzwznbSP3mn0hn N6DegsykcYhHycKH6ifjZiMN+SGGeNsi5rhoW5Cj9ptw3C3yQnrFNDbS GZCT97z5lpQU3ZcvP4RDNk7dhri7Bh3SJeaCFoqx00NgFvlBR48hosSG bGUbUKzNf58GBTkW4Us2jIWsreZx8LLLev232Hy7NU9L19k+hVq7pJOf Uvtrn5fmGSutWOzsR+8EacOnh0lwssCKjutk5MSmfdFC5P7CTZkdq58L 8he13HGmr00= diff --git a/lib/dns/tests/testdata/nsec3/4096.db b/lib/dns/tests/testdata/nsec3/4096.db new file mode 100644 index 0000000..b5c8b7e --- /dev/null +++ b/lib/dns/tests/testdata/nsec3/4096.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 4096 bits +test. IN DNSKEY 256 3 5 AwEAAbYlqbKxXoq9mzkqdsAaSZ3XywBVAb2sCTgrQBCExyGEYNpWw3LN +imCrLQi7jHKQW6GZIqKNgQaiFEwr3zK8nPWbwNwyKU9a2hhINv/gim1 5iA87Vu7DiiJrQ0O79ospvsGsKknBQ41zaaQMp3Q/W1S6WNe4uyh4C/f R0qmxT+8MyXEqCpTGb+e+YT6BuqpNQPuYYYvUJ1/HJltzY/lY2b9RZ+Q ZJ23Zje79YIRM0kJapqj11fDUDeynhDL1DUikYCwRfQiO/blChhOHjIa uTK1qqRY3fqanLGOufpLTr7GRpL7RxeRIMJfDzmcjFLmCsMA1AJ56Bxq jiXr3ODgn9D30vAB74Lr7lqLQSWyrSlJjoZLLhmPrEP/nnuCxEhOhDRA XJpJWpcQ4Hdu+yb5K/qldnsGLLI1Hr0GmhLTDHsxDb6BxM7/8rv8QeQY GKSGshBqD2lO1xUVT8inbi8uXI1iyN68vHX6xoFT5wsjls70PxSZPO5i F40vn6BWNsHtKWOCDqMKYx8hYwiv0zETVwxBaj58vylFwYGU+g1wIQmF Pgi2HKv4KaxgikUvdFISre5rxVoG5VrmmXWiNJcLTbwZ+tE1xujCNU1c V31CaIB5hdSnkEvQADr5V64RTxWAKuSLNMU+XUqTkaJHasSm3OPJOteo SPj2uoesuxNFYps3 diff --git a/lib/dns/tests/testdata/nsec3/min-1024.db b/lib/dns/tests/testdata/nsec3/min-1024.db new file mode 100644 index 0000000..7d0f95c --- /dev/null +++ b/lib/dns/tests/testdata/nsec3/min-1024.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 1024 bit key. +test. IN DNSKEY 256 3 5 AwEAAd5oKx06HRE6NRrTDz49lljdRmxgp/4YB/cyMkpwUMkaLhDNCfTq hql84ab2LRbtUWLHFXGWENvxPGQzVHeleXu+3ThNfFOwIaySedxHmLGT lTtBRDhPc8iSb+2IYDemmA+ut8kwHhCVz/tDMbD/dgAswdOtmXCpQyJk Q1HqY3Xj +; 2048 bits +test. IN DNSKEY 256 3 5 AwEAAcfQX59iZr9gK+XzhTZQ5KWrfCLA0iYHTqheEIhC2dXS8gUSppQS g9SmzH2129u/LSSb7gqJSoLLAsn36iinqCqUXl2BT6xzwznbSP3mn0hn N6DegsykcYhHycKH6ifjZiMN+SGGeNsi5rhoW5Cj9ptw3C3yQnrFNDbS GZCT97z5lpQU3ZcvP4RDNk7dhri7Bh3SJeaCFoqx00NgFvlBR48hosSG bGUbUKzNf58GBTkW4Us2jIWsreZx8LLLev232Hy7NU9L19k+hVq7pJOf Uvtrn5fmGSutWOzsR+8EacOnh0lwssCKjutk5MSmfdFC5P7CTZkdq58L 8he13HGmr00= +; 4096 bits +test. IN DNSKEY 256 3 5 AwEAAbYlqbKxXoq9mzkqdsAaSZ3XywBVAb2sCTgrQBCExyGEYNpWw3LN +imCrLQi7jHKQW6GZIqKNgQaiFEwr3zK8nPWbwNwyKU9a2hhINv/gim1 5iA87Vu7DiiJrQ0O79ospvsGsKknBQ41zaaQMp3Q/W1S6WNe4uyh4C/f R0qmxT+8MyXEqCpTGb+e+YT6BuqpNQPuYYYvUJ1/HJltzY/lY2b9RZ+Q ZJ23Zje79YIRM0kJapqj11fDUDeynhDL1DUikYCwRfQiO/blChhOHjIa uTK1qqRY3fqanLGOufpLTr7GRpL7RxeRIMJfDzmcjFLmCsMA1AJ56Bxq jiXr3ODgn9D30vAB74Lr7lqLQSWyrSlJjoZLLhmPrEP/nnuCxEhOhDRA XJpJWpcQ4Hdu+yb5K/qldnsGLLI1Hr0GmhLTDHsxDb6BxM7/8rv8QeQY GKSGshBqD2lO1xUVT8inbi8uXI1iyN68vHX6xoFT5wsjls70PxSZPO5i F40vn6BWNsHtKWOCDqMKYx8hYwiv0zETVwxBaj58vylFwYGU+g1wIQmF Pgi2HKv4KaxgikUvdFISre5rxVoG5VrmmXWiNJcLTbwZ+tE1xujCNU1c V31CaIB5hdSnkEvQADr5V64RTxWAKuSLNMU+XUqTkaJHasSm3OPJOteo SPj2uoesuxNFYps3 diff --git a/lib/dns/tests/testdata/nsec3/min-2048.db b/lib/dns/tests/testdata/nsec3/min-2048.db new file mode 100644 index 0000000..027c0b9 --- /dev/null +++ b/lib/dns/tests/testdata/nsec3/min-2048.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 2048 bits +test. IN DNSKEY 256 3 5 AwEAAcfQX59iZr9gK+XzhTZQ5KWrfCLA0iYHTqheEIhC2dXS8gUSppQS g9SmzH2129u/LSSb7gqJSoLLAsn36iinqCqUXl2BT6xzwznbSP3mn0hn N6DegsykcYhHycKH6ifjZiMN+SGGeNsi5rhoW5Cj9ptw3C3yQnrFNDbS GZCT97z5lpQU3ZcvP4RDNk7dhri7Bh3SJeaCFoqx00NgFvlBR48hosSG bGUbUKzNf58GBTkW4Us2jIWsreZx8LLLev232Hy7NU9L19k+hVq7pJOf Uvtrn5fmGSutWOzsR+8EacOnh0lwssCKjutk5MSmfdFC5P7CTZkdq58L 8he13HGmr00= +; 4096 bits +test. IN DNSKEY 256 3 5 AwEAAbYlqbKxXoq9mzkqdsAaSZ3XywBVAb2sCTgrQBCExyGEYNpWw3LN +imCrLQi7jHKQW6GZIqKNgQaiFEwr3zK8nPWbwNwyKU9a2hhINv/gim1 5iA87Vu7DiiJrQ0O79ospvsGsKknBQ41zaaQMp3Q/W1S6WNe4uyh4C/f R0qmxT+8MyXEqCpTGb+e+YT6BuqpNQPuYYYvUJ1/HJltzY/lY2b9RZ+Q ZJ23Zje79YIRM0kJapqj11fDUDeynhDL1DUikYCwRfQiO/blChhOHjIa uTK1qqRY3fqanLGOufpLTr7GRpL7RxeRIMJfDzmcjFLmCsMA1AJ56Bxq jiXr3ODgn9D30vAB74Lr7lqLQSWyrSlJjoZLLhmPrEP/nnuCxEhOhDRA XJpJWpcQ4Hdu+yb5K/qldnsGLLI1Hr0GmhLTDHsxDb6BxM7/8rv8QeQY GKSGshBqD2lO1xUVT8inbi8uXI1iyN68vHX6xoFT5wsjls70PxSZPO5i F40vn6BWNsHtKWOCDqMKYx8hYwiv0zETVwxBaj58vylFwYGU+g1wIQmF Pgi2HKv4KaxgikUvdFISre5rxVoG5VrmmXWiNJcLTbwZ+tE1xujCNU1c V31CaIB5hdSnkEvQADr5V64RTxWAKuSLNMU+XUqTkaJHasSm3OPJOteo SPj2uoesuxNFYps3 diff --git a/lib/dns/tests/testdata/zt/zone1.db b/lib/dns/tests/testdata/zt/zone1.db new file mode 100644 index 0000000..8286d88 --- /dev/null +++ b/lib/dns/tests/testdata/zt/zone1.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. +a in a 1.2.3.4 diff --git a/lib/dns/tests/testkeys/Kexample.+008+20386.key b/lib/dns/tests/testkeys/Kexample.+008+20386.key new file mode 100644 index 0000000..3404dca --- /dev/null +++ b/lib/dns/tests/testkeys/Kexample.+008+20386.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 20386, for example. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example. IN DNSKEY 257 3 8 AwEAAZd7/hBRvMooz0sepkD/2r3Bp021f8lGzDj6sZEVbg1hcqZTzURc eGkS541wyOqjvJv2KBi5qLLE2HthmexmOBycjTQ7EiKd1P9bE8RgF8Et j73X/CHLiX6YL7cb93TXWiUvbRh4E6D2URgOmxMdMOXTuCvjvDaGVCOt Jc77UUosuBeurZzP8g8t/zccAUTzu2cdRyI5/ZxOBfJaDtc9TlRdWsaN Af+nT0C14ccH7QVlKjjaYV4lXueruDW3yTTzu9bQ1ikgegsCLi/tcD/1 dWTOI9whV06szs+ouhuJkZuhIjrGDtOHCpjPjIxOOrIZceU1YSY30kAR QNVzshJqyx8= diff --git a/lib/dns/tests/testkeys/Kexample.+008+20386.private b/lib/dns/tests/testkeys/Kexample.+008+20386.private new file mode 100644 index 0000000..d8cff93 --- /dev/null +++ b/lib/dns/tests/testkeys/Kexample.+008+20386.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: l3v+EFG8yijPSx6mQP/avcGnTbV/yUbMOPqxkRVuDWFyplPNRFx4aRLnjXDI6qO8m/YoGLmossTYe2GZ7GY4HJyNNDsSIp3U/1sTxGAXwS2Pvdf8IcuJfpgvtxv3dNdaJS9tGHgToPZRGA6bEx0w5dO4K+O8NoZUI60lzvtRSiy4F66tnM/yDy3/NxwBRPO7Zx1HIjn9nE4F8loO1z1OVF1axo0B/6dPQLXhxwftBWUqONphXiVe56u4NbfJNPO71tDWKSB6CwIuL+1wP/V1ZM4j3CFXTqzOz6i6G4mRm6EiOsYO04cKmM+MjE46shlx5TVhJjfSQBFA1XOyEmrLHw== +PublicExponent: AQAB +PrivateExponent: aSkynrGfldfuz/9e+xCjEcg2FMRDCb+UVpnyWv29gJx9sunKPgLTtF3jUVVSpVE1xi+EdmWsry3n+v8uk+YCXhpwDCpV1KItE3huqIzs8LZoaypdZjieIrwTo9JOX1aAxf++hJYXSk60zTaWgRZqs6He4Nkf99oY3wt8i8v8CrkfQy76K/qK9xUVv5GHrEZzCGLfLv77eqDab/J84ANxc0kUtQvgt2/JTHofXmcA6/YDh5PWB8KRw1PjQTck61/xIgfI6ky/yIF1riCQCYXwTv7jcmMV/QvQ+dfN+HZ2CSGp7xcH2Yxe9OhAY823ZkmkOQ2YZPjIj6dEoRMmSiaagQ== +Prime1: x2GMnpRPwvUhM+yPRa7nh5Jjl4mbofeOtVrxe1hEVy8l2UGFh+FDZCbyoLRNUTYDji00NHpGtmcAyoY9pLdOn7ci4zqGVnNJcIY75Ie4p6J7pPfDh9d+AGtJ5NpNhr1sjD0bFncJC2FGY9vj4eC0CkatMu/Qovrd2FwZ8VpDsAk= +Prime2: woB8MYsEfSYGD0hZGtmgK6UQ+Oo9smxdPmahLYXnLSAdqtqZbZX+ABk/kFduT+XwlHOXmp3HMmUtQTRZBaQyBrsFWfWjOGevByEsT9aLQSZOEgnqy4xrc9XNwDs4/WkrEgw/TOVnZYdaCyLxsFl4bpTX8Fj3yVqg/tJvuUMWG+c= +Exponent1: iQO7a9rF+VcVSyZ8yslIaL0r3Z5+Kk8CbhSiMD5XMIbA/sztI5SlCDVPtSpSm8V/qfvcjVeeMokUXRjlUcV6rX1f50F3wf8V79L/Y6v1NJYPXC273CU1fLo+HJv8fOS9rJ3teIGy4HQnuEYLE1WkxA8PxRpSiT3WqHGajmaWb2k= +Exponent2: elMWSI5Wz2KXkwr8Rz+xVWGl7/ZZwRoX9oPTQG8jeiTlo6uBrQMVUPiQGnZyQTuq96JPKYWrXs11DbofdsXSVJtQfUhYU8QZtxEs7jVPNTUjCoNEMKnqdlpz4T8d03pOBTbApNruEVNz1OcwO6m5bUqdGGLLy838zOaKL2i6wec= +Coefficient: q2mejAmT3A4H2C0rT1hm8XQFuISHjAAEyM9t09Q8tEeQ0lHi4gMVA3bXoAn9U21eBkFQDwvyB0vqlVSGgRqHovOKx9uXAU9eoDxGcJsFlGsM0aUsUjGVXv5kVmaw8a5PHBbvYAbgAZUmKqrVF0PWD3o+/DbzP9PCmlJcqxoAulU= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/lib/dns/tests/testkeys/Kexample.+008+37464.key b/lib/dns/tests/testkeys/Kexample.+008+37464.key new file mode 100644 index 0000000..3dd0619 --- /dev/null +++ b/lib/dns/tests/testkeys/Kexample.+008+37464.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 37464, for example. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example. IN DNSKEY 256 3 8 AwEAAbxHOF8G0xw9ekCodhL8KivuZ3o0jmGlycLiXBjBN8c5R5fjLjUh D0gy3IDbDC+kLaPhHGF/MwrSEjrgSowxZ8nrxDzsq5ZdpeUsYaNrbQEY /mqf35T/9/Ulm4v06x58v/NTugWd05Xq04aAyfm7EViyGFzmVOVfPnll h9xQtvWEWoRWPseFw+dY5/nc/+xB/IsQMihoH2rO+cek/lsP3R9DsHCG RbQ/ks/+rrp6/O+QJZyZrzsONl7mlMDXNy3Pz9J4qMW2W6Mz702LN324 7/9UsetDGGbuZfrCLMpKWXzdsJm36DOk4aMooS9111plfXaXQgQNcL5G 021utpTau+8= diff --git a/lib/dns/tests/testkeys/Kexample.+008+37464.private b/lib/dns/tests/testkeys/Kexample.+008+37464.private new file mode 100644 index 0000000..ecc2ad0 --- /dev/null +++ b/lib/dns/tests/testkeys/Kexample.+008+37464.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: vEc4XwbTHD16QKh2EvwqK+5nejSOYaXJwuJcGME3xzlHl+MuNSEPSDLcgNsML6Qto+EcYX8zCtISOuBKjDFnyevEPOyrll2l5Sxho2ttARj+ap/flP/39SWbi/TrHny/81O6BZ3TlerThoDJ+bsRWLIYXOZU5V8+eWWH3FC29YRahFY+x4XD51jn+dz/7EH8ixAyKGgfas75x6T+Ww/dH0OwcIZFtD+Sz/6uunr875AlnJmvOw42XuaUwNc3Lc/P0nioxbZbozPvTYs3fbjv/1Sx60MYZu5l+sIsykpZfN2wmbfoM6ThoyihL3XXWmV9dpdCBA1wvkbTbW62lNq77w== +PublicExponent: AQAB +PrivateExponent: AhR3VvVoV6OGOjiiNUt728hidEMoX4PJWtHNWqinyRek5tSnqgaXeKC3NuU0mUIjDvBps9oH4lK3yNa5fBr/nodwP4wNyTd3obR/z6JcLersxJjHi4nYX2ju8vjdsBSIulNudqlrsPhLJe0+Tff3FRfClSQmQ/JtakHo4lIx8zxiOJY8aWFeHGdWJDkAf6NStt3eVYyOyAwISfv3muaGPZKShiIOfLyTvqFqzwYFgdTWmvFqTdwgjIMc5XAwqw73WP2BPCN+fdCiMtrw0fCrhWzw/gfMJBHdOPH0diUZysAJhM0vdVKQzEi/g3YOo00fahZiPzaxNtZnLNj2mA54YQ== +Prime1: 5YpfVjEtL1owW9gSFbIMx65POr+fiktxirgy1bc5fSsVqUgG6zhbaN/VpWcNZG0Zg5xd6S7C8V3djGlnJN8wZIyjIh7+Z3WWjqbOD9oY7rC1fR+W0OvbCmZiEzOpRJ5qoMOh1MzkkanhMy0/ICpaa8eQ9zEb80oTIQpFgoLn7K0= +Prime2: 0fs3ncL5/2qzq2dmPXLYcOfc1EGSuESO0VpREP8EpTkyPKeVw5LaF9TgZRqPWlRf2T0LPoZ766xLAn090u0pLQ5fWM96NMas7kS+rxtRssat6MiQo3YfoU3ysk3xuPzrMBHyn/N42CjSG+bJEToHR7V16KsCT6dBIPkI3tj/Yos= +Exponent1: Bdsp44ENrg+W/EDe9T69pLqFuvH4mAaktu1MHre198OJoe/8fTPK4ToUsUuXw+Akrn7mxnQy9QV4CYUG5KHtEiOkZdJ0mx8c4DbROwZNbImFl9OefWYHCJTkG6lNwDpqbf+PuWYgzraO0EdvPNrXw7grsqLGG8bgBg/FBjdgw2E= +Exponent2: uV1pxW0fwGhzX3aR/ODrTRCCEyYn3V84LHvsYHKfqTOKs5zFSrbSrIMR7G676ePeESogSPvzXSLlvLbO4urVlJ7BcOcHXJuegWBSbMZTItzdHUgg1wwp8/2Zp+nC36j1/aN6adVG8ptmj5b2HKz7TERWaCS+j454oiD1wbQSDu0= +Coefficient: JO6RxBIaoEd/Z4ITcsYT8TslP1KmIuAqdhMt3FSpqeogUDut7f3FZIEyNi4wsrSK5peIQSVmO2pQLupS+eRIPHXZ1vh5kcFAsgd7XBb7Fvsg26/WSjhB4wjx+wgWzVomK0519pfdtH854fePWPkdDKtLNL2zh0APne3GjwrbNEM= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/lib/dns/tests/time_test.c b/lib/dns/tests/time_test.c new file mode 100644 index 0000000..28b72b6 --- /dev/null +++ b/lib/dns/tests/time_test.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <inttypes.h> +#include <unistd.h> + +#include <dns/time.h> + +#include "dnstest.h" + +#define TEST_ORIGIN "test" + +/* + * Individual unit tests + */ + +/* value = 0xfffffffff <-> 19691231235959 */ +ATF_TC(epoch_minus_one); +ATF_TC_HEAD(epoch_minus_one, tc) { + atf_tc_set_md_var(tc, "descr", "0xffffffff <-> 19691231235959"); +} +ATF_TC_BODY(epoch_minus_one, tc) { + const char *test_text = "19691231235959"; + const uint32_t test_time = 0xffffffff; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_STREQ(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(when, test_time); + dns_test_end(); +} + +/* value = 0x000000000 <-> 19700101000000*/ +ATF_TC(epoch); +ATF_TC_HEAD(epoch, tc) { + atf_tc_set_md_var(tc, "descr", "0x00000000 <-> 19700101000000"); +} +ATF_TC_BODY(epoch, tc) { + const char *test_text = "19700101000000"; + const uint32_t test_time = 0x00000000; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_STREQ(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(when, test_time); + dns_test_end(); +} + +/* value = 0x7fffffff <-> 20380119031407 */ +ATF_TC(half_maxint); +ATF_TC_HEAD(half_maxint, tc) { + atf_tc_set_md_var(tc, "descr", "0x7fffffff <-> 20380119031407"); +} +ATF_TC_BODY(half_maxint, tc) { + const char *test_text = "20380119031407"; + const uint32_t test_time = 0x7fffffff; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_STREQ(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(when, test_time); + dns_test_end(); +} + +/* value = 0x80000000 <-> 20380119031408 */ +ATF_TC(half_plus_one); +ATF_TC_HEAD(half_plus_one, tc) { + atf_tc_set_md_var(tc, "descr", "0x80000000 <-> 20380119031408"); +} +ATF_TC_BODY(half_plus_one, tc) { + const char *test_text = "20380119031408"; + const uint32_t test_time = 0x80000000; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_STREQ(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(when, test_time); + dns_test_end(); +} + +/* value = 0xef68f5d0 <-> 19610307130000 */ +ATF_TC(fifty_before); +ATF_TC_HEAD(fifty_before, tc) { + atf_tc_set_md_var(tc, "descr", "0xef68f5d0 <-> 19610307130000"); +} +ATF_TC_BODY(fifty_before, tc) { + isc_result_t result; + const char *test_text = "19610307130000"; + const uint32_t test_time = 0xef68f5d0; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_STREQ(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(when, test_time); + dns_test_end(); +} + +/* value = 0x4d74d6d0 <-> 20110307130000 */ +ATF_TC(some_ago); +ATF_TC_HEAD(some_ago, tc) { + atf_tc_set_md_var(tc, "descr", "0x4d74d6d0 <-> 20110307130000"); +} +ATF_TC_BODY(some_ago, tc) { + const char *test_text = "20110307130000"; + const uint32_t test_time = 0x4d74d6d0; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_STREQ(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(when, test_time); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, epoch_minus_one); + ATF_TP_ADD_TC(tp, epoch); + ATF_TP_ADD_TC(tp, half_maxint); + ATF_TP_ADD_TC(tp, half_plus_one); + ATF_TP_ADD_TC(tp, fifty_before); + ATF_TP_ADD_TC(tp, some_ago); + + return (atf_no_error()); +} + diff --git a/lib/dns/tests/tsig_test.c b/lib/dns/tests/tsig_test.c new file mode 100644 index 0000000..443fb36 --- /dev/null +++ b/lib/dns/tests/tsig_test.c @@ -0,0 +1,491 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include <config.h> +#include <atf-c.h> + +#include <isc/mem.h> +#include <isc/print.h> + +#include <dns/rdatalist.h> +#include <dns/rdataset.h> +#include <dns/tsig.h> + +#include "dnstest.h" + + +static int debug = 0; + +static isc_result_t +add_mac(dst_context_t *tsigctx, isc_buffer_t *buf) { + dns_rdata_any_tsig_t tsig; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_buffer_t databuf; + isc_region_t r; + isc_result_t result; + unsigned char tsigbuf[1024]; + + isc_buffer_usedregion(buf, &r); + dns_rdata_fromregion(&rdata, dns_rdataclass_any, + dns_rdatatype_tsig, &r); + isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf)); + CHECK(dns_rdata_tostruct(&rdata, &tsig, NULL)); + isc_buffer_putuint16(&databuf, tsig.siglen); + isc_buffer_putmem(&databuf, tsig.signature, tsig.siglen); + isc_buffer_usedregion(&databuf, &r); + result = dst_context_adddata(tsigctx, &r); + dns_rdata_freestruct(&tsig); + cleanup: + return (result); +} + +static isc_result_t +add_tsig(dst_context_t *tsigctx, dns_tsigkey_t *key, isc_buffer_t *target) { + dns_compress_t cctx; + dns_rdata_any_tsig_t tsig; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + isc_buffer_t *dynbuf = NULL; + isc_buffer_t databuf; + isc_buffer_t sigbuf; + isc_region_t r; + isc_result_t result = ISC_R_SUCCESS; + isc_stdtime_t now; + unsigned char tsigbuf[1024]; + unsigned int count; + unsigned int sigsize = 0; + bool invalidate_ctx = false; + + memset(&tsig, 0, sizeof(tsig)); + + CHECK(dns_compress_init(&cctx, -1, mctx)); + invalidate_ctx = true; + + tsig.common.rdclass = dns_rdataclass_any; + tsig.common.rdtype = dns_rdatatype_tsig; + ISC_LINK_INIT(&tsig.common, link); + dns_name_init(&tsig.algorithm, NULL); + dns_name_clone(key->algorithm, &tsig.algorithm); + + isc_stdtime_get(&now); + tsig.timesigned = now; + tsig.fudge = DNS_TSIG_FUDGE; + tsig.originalid = 50; + tsig.error = dns_rcode_noerror; + tsig.otherlen = 0; + tsig.other = NULL; + + isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf)); + isc_buffer_putuint48(&databuf, tsig.timesigned); + isc_buffer_putuint16(&databuf, tsig.fudge); + isc_buffer_usedregion(&databuf, &r); + CHECK(dst_context_adddata(tsigctx, &r)); + + CHECK(dst_key_sigsize(key->key, &sigsize)); + tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize); + if (tsig.signature == NULL) + CHECK(ISC_R_NOMEMORY); + isc_buffer_init(&sigbuf, tsig.signature, sigsize); + CHECK(dst_context_sign(tsigctx, &sigbuf)); + tsig.siglen = isc_buffer_usedlength(&sigbuf); + ATF_CHECK_EQ(sigsize, tsig.siglen); + + CHECK(isc_buffer_allocate(mctx, &dynbuf, 512)); + CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_any, + dns_rdatatype_tsig, &tsig, dynbuf)); + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = dns_rdataclass_any; + rdatalist.type = dns_rdatatype_tsig; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + dns_rdataset_init(&rdataset); + CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); + CHECK(dns_rdataset_towire(&rdataset, &key->name, &cctx, + target, 0, &count)); + + /* + * Fixup additional record count. + */ + ((unsigned char*)target->base)[11]++; + if (((unsigned char*)target->base)[11] == 0) + ((unsigned char*)target->base)[10]++; + cleanup: + if (tsig.signature != NULL) + isc_mem_put(mctx, tsig.signature, sigsize); + if (dynbuf != NULL) + isc_buffer_free(&dynbuf); + if (invalidate_ctx) + dns_compress_invalidate(&cctx); + + return (result); +} + +static void +printmessage(dns_message_t *msg) { + isc_buffer_t b; + char *buf = NULL; + int len = 1024; + isc_result_t result = ISC_R_SUCCESS; + + if (!debug) + return; + + do { + buf = isc_mem_get(mctx, len); + if (buf == NULL) + return; + + isc_buffer_init(&b, buf, len); + result = dns_message_totext(msg, &dns_master_style_debug, + 0, &b); + if (result == ISC_R_NOSPACE) { + isc_mem_put(mctx, buf, len); + len *= 2; + } else if (result == ISC_R_SUCCESS) + printf("%.*s\n", (int) isc_buffer_usedlength(&b), buf); + } while (result == ISC_R_NOSPACE); + + if (buf != NULL) + isc_mem_put(mctx, buf, len); +} + +static void +render(isc_buffer_t *buf, unsigned flags, dns_tsigkey_t *key, + isc_buffer_t **tsigin, isc_buffer_t **tsigout, + dst_context_t *tsigctx) +{ + dns_message_t *msg = NULL; + dns_compress_t cctx; + isc_result_t result; + + result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &msg); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_create: %s", + dns_result_totext(result)); + ATF_REQUIRE(msg != NULL); + + msg->id = 50; + msg->rcode = dns_rcode_noerror; + msg->flags = flags; + + /* + * XXXMPA: this hack needs to be replaced with use of + * dns_message_reply() at some point. + */ + if ((flags & DNS_MESSAGEFLAG_QR) != 0) + msg->verified_sig = 1; + + if (tsigin == tsigout) + msg->tcp_continuation = 1; + + if (tsigctx == NULL) { + result = dns_message_settsigkey(msg, key); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_settsigkey: %s", + dns_result_totext(result)); + + result = dns_message_setquerytsig(msg, *tsigin); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_setquerytsig: %s", + dns_result_totext(result)); + } + + result = dns_compress_init(&cctx, -1, mctx); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_compress_init: %s", + dns_result_totext(result)); + + result = dns_message_renderbegin(msg, &cctx, buf); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_renderbegin: %s", + dns_result_totext(result)); + + result = dns_message_renderend(msg); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_renderend: %s", + dns_result_totext(result)); + + if (tsigctx != NULL) { + isc_region_t r; + + isc_buffer_usedregion(buf, &r); + result = dst_context_adddata(tsigctx, &r); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dst_context_adddata: %s", + dns_result_totext(result)); + } else { + if (tsigin == tsigout && *tsigin != NULL) + isc_buffer_free(tsigin); + + result = dns_message_getquerytsig(msg, mctx, tsigout); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_getquerytsig: %s", + dns_result_totext(result)); + } + + dns_compress_invalidate(&cctx); + dns_message_destroy(&msg); +} + +/* + * Check that a simulated three message TCP sequence where the first + * and last messages contain TSIGs but the intermediate message doesn't + * correctly verifies. + */ +ATF_TC(tsig_tcp); +ATF_TC_HEAD(tsig_tcp, tc) { + atf_tc_set_md_var(tc, "descr", "test tsig tcp-continuation validation"); +} +ATF_TC_BODY(tsig_tcp, tc) { + dns_name_t *tsigowner = NULL; + dns_fixedname_t fkeyname; + dns_message_t *msg = NULL; + dns_name_t *keyname; + dns_tsig_keyring_t *ring = NULL; + dns_tsigkey_t *key = NULL; + isc_buffer_t *buf = NULL; + isc_buffer_t *querytsig = NULL; + isc_buffer_t *tsigin = NULL; + isc_buffer_t *tsigout = NULL; + isc_result_t result; + unsigned char secret[16] = { 0 }; + dst_context_t *tsigctx = NULL; + dst_context_t *outctx = NULL; + + UNUSED(tc); + + result = dns_test_begin(stderr, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* isc_log_setdebuglevel(lctx, 99); */ + + keyname = dns_fixedname_initname(&fkeyname); + result = dns_name_fromstring(keyname, "test", 0, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_tsigkeyring_create(mctx, &ring); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_tsigkey_create(keyname, dns_tsig_hmacsha256_name, + secret, sizeof(secret), false, + NULL, 0, 0, mctx, ring, &key); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE(key != NULL); + + /* + * Create request. + */ + result = isc_buffer_allocate(mctx, &buf, 65535); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + render(buf, 0, key, &tsigout, &querytsig, NULL); + isc_buffer_free(&buf); + + /* + * Create response message 1. + */ + result = isc_buffer_allocate(mctx, &buf, 65535); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + render(buf, DNS_MESSAGEFLAG_QR, key, &querytsig, &tsigout, NULL); + + /* + * Process response message 1. + */ + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_create: %s", + dns_result_totext(result)); + ATF_REQUIRE(msg != NULL); + + result = dns_message_settsigkey(msg, key); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_settsigkey: %s", + dns_result_totext(result)); + + result = dns_message_parse(msg, buf, 0); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_parse: %s", + dns_result_totext(result)); + + printmessage(msg); + + result = dns_message_setquerytsig(msg, querytsig); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_setquerytsig: %s", + dns_result_totext(result)); + + result = dns_tsig_verify(buf, msg, NULL, NULL); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_tsig_verify: %s", + dns_result_totext(result)); + ATF_CHECK_EQ(msg->verified_sig, 1); + ATF_CHECK_EQ(msg->tsigstatus, dns_rcode_noerror); + + /* + * Check that we have a TSIG in the first message. + */ + ATF_REQUIRE(dns_message_gettsig(msg, &tsigowner) != NULL); + + result = dns_message_getquerytsig(msg, mctx, &tsigin); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_getquerytsig: %s", + dns_result_totext(result)); + + tsigctx = msg->tsigctx; + msg->tsigctx = NULL; + isc_buffer_free(&buf); + dns_message_destroy(&msg); + + result = dst_context_create3(key->key, mctx, DNS_LOGCATEGORY_DNSSEC, + false, &outctx); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE(outctx != NULL); + + /* + * Start digesting. + */ + result = add_mac(outctx, tsigout); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Create response message 2. + */ + result = isc_buffer_allocate(mctx, &buf, 65535); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + render(buf, DNS_MESSAGEFLAG_QR, key, &tsigout, &tsigout, outctx); + + /* + * Process response message 2. + */ + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_create: %s", + dns_result_totext(result)); + ATF_REQUIRE(msg != NULL); + + msg->tcp_continuation = 1; + msg->tsigctx = tsigctx; + tsigctx = NULL; + + result = dns_message_settsigkey(msg, key); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_settsigkey: %s", + dns_result_totext(result)); + + result = dns_message_parse(msg, buf, 0); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_parse: %s", + dns_result_totext(result)); + + printmessage(msg); + + result = dns_message_setquerytsig(msg, tsigin); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_setquerytsig: %s", + dns_result_totext(result)); + + result = dns_tsig_verify(buf, msg, NULL, NULL); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_tsig_verify: %s", + dns_result_totext(result)); + ATF_CHECK_EQ(msg->verified_sig, 0); + ATF_CHECK_EQ(msg->tsigstatus, dns_rcode_noerror); + + /* + * Check that we don't have a TSIG in the second message. + */ + tsigowner = NULL; + ATF_REQUIRE(dns_message_gettsig(msg, &tsigowner) == NULL); + + tsigctx = msg->tsigctx; + msg->tsigctx = NULL; + isc_buffer_free(&buf); + dns_message_destroy(&msg); + + /* + * Create response message 3. + */ + result = isc_buffer_allocate(mctx, &buf, 65535); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + render(buf, DNS_MESSAGEFLAG_QR, key, &tsigout, &tsigout, outctx); + + result = add_tsig(outctx, key, buf); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "add_tsig: %s", + dns_result_totext(result)); + + /* + * Process response message 3. + */ + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_create: %s", + dns_result_totext(result)); + ATF_REQUIRE(msg != NULL); + + msg->tcp_continuation = 1; + msg->tsigctx = tsigctx; + tsigctx = NULL; + + result = dns_message_settsigkey(msg, key); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_settsigkey: %s", + dns_result_totext(result)); + + result = dns_message_parse(msg, buf, 0); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "dns_message_parse: %s", + dns_result_totext(result)); + + printmessage(msg); + + /* + * Check that we had a TSIG in the third message. + */ + ATF_REQUIRE(dns_message_gettsig(msg, &tsigowner) != NULL); + + result = dns_message_setquerytsig(msg, tsigin); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_setquerytsig: %s", + dns_result_totext(result)); + + result = dns_tsig_verify(buf, msg, NULL, NULL); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, + "dns_tsig_verify: %s", + dns_result_totext(result)); + ATF_CHECK_EQ(msg->verified_sig, 1); + ATF_CHECK_EQ(msg->tsigstatus, dns_rcode_noerror); + + if (tsigin != NULL) + isc_buffer_free(&tsigin); + + result = dns_message_getquerytsig(msg, mctx, &tsigin); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, + "dns_message_getquerytsig: %s", + dns_result_totext(result)); + + isc_buffer_free(&buf); + dns_message_destroy(&msg); + + if (outctx != NULL) + dst_context_destroy(&outctx); + if (querytsig != NULL) + isc_buffer_free(&querytsig); + if (tsigin != NULL) + isc_buffer_free(&tsigin); + if (tsigout != NULL) + isc_buffer_free(&tsigout); + dns_tsigkey_detach(&key); + if (ring != NULL) + dns_tsigkeyring_detach(&ring); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, tsig_tcp); + return (atf_no_error()); +} diff --git a/lib/dns/tests/update_test.c b/lib/dns/tests/update_test.c new file mode 100644 index 0000000..1585ed7 --- /dev/null +++ b/lib/dns/tests/update_test.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <inttypes.h> +#include <unistd.h> +#include <time.h> + +#include <isc/serial.h> +#include <isc/stdtime.h> + +#include <dns/update.h> + +#include "dnstest.h" + +static uint32_t mystdtime; + +static void set_mystdtime(int year, int month, int day) { + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = day; + mystdtime = timegm(&tm) ; +} + +void isc_stdtime_get(isc_stdtime_t *now) { + *now = mystdtime; +} + +/* + * Individual unit tests + */ + +ATF_TC(increment); +ATF_TC_HEAD(increment, tc) { + atf_tc_set_md_var(tc, "descr", "simple increment by 1"); +} +ATF_TC_BODY(increment, tc) { + uint32_t old = 50; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_increment); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK_MSG(serial != 0, "serial (%d) should not equal 0", serial); + ATF_REQUIRE_EQ(serial, 51); + dns_test_end(); +} + +/* 0xfffffffff -> 1 */ +ATF_TC(increment_past_zero); +ATF_TC_HEAD(increment_past_zero, tc) { + atf_tc_set_md_var(tc, "descr", "increment past zero, ffffffff -> 1"); +} +ATF_TC_BODY(increment_past_zero, tc) { + uint32_t old = 0xffffffffu; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_increment); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, 1u); + dns_test_end(); +} + +ATF_TC(past_to_unix); +ATF_TC_HEAD(past_to_unix, tc) { + atf_tc_set_md_var(tc, "descr", "past to unixtime"); +} +ATF_TC_BODY(past_to_unix, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2011, 6, 22); + old = mystdtime - 1; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, mystdtime); + dns_test_end(); +} + +ATF_TC(now_to_unix); +ATF_TC_HEAD(now_to_unix, tc) { + atf_tc_set_md_var(tc, "descr", "now to unixtime"); +} +ATF_TC_BODY(now_to_unix, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2011, 6, 22); + old = mystdtime; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, old + 1); + dns_test_end(); +} + +ATF_TC(future_to_unix); +ATF_TC_HEAD(future_to_unix, tc) { + atf_tc_set_md_var(tc, "descr", "future to unixtime"); +} +ATF_TC_BODY(future_to_unix, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2011, 6, 22); + old = mystdtime + 1; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, old + 1); + dns_test_end(); +} + +ATF_TC(undefined_plus1_to_unix); +ATF_TC_HEAD(undefined_plus1_to_unix, tc) { + atf_tc_set_md_var(tc, "descr", "undefined plus 1 to unixtime"); +} +ATF_TC_BODY(undefined_plus1_to_unix, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2011, 6, 22); + old = mystdtime ^ 0x80000000u; + old += 1; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, mystdtime); + dns_test_end(); +} + +ATF_TC(undefined_minus1_to_unix); +ATF_TC_HEAD(undefined_minus1_to_unix, tc) { + atf_tc_set_md_var(tc, "descr", "undefined minus 1 to unixtime"); +} +ATF_TC_BODY(undefined_minus1_to_unix, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2011, 6, 22); + old = mystdtime ^ 0x80000000u; + old -= 1; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, old + 1); + dns_test_end(); +} + +ATF_TC(undefined_to_unix); +ATF_TC_HEAD(undefined_to_unix, tc) { + atf_tc_set_md_var(tc, "descr", "undefined to unixtime"); +} +ATF_TC_BODY(undefined_to_unix, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2011, 6, 22); + old = mystdtime ^ 0x80000000u; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, old + 1); + dns_test_end(); +} + +ATF_TC(unixtime_zero); +ATF_TC_HEAD(unixtime_zero, tc) { + atf_tc_set_md_var(tc, "descr", "handle unixtime being zero"); +} +ATF_TC_BODY(unixtime_zero, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + mystdtime = 0; + old = 0xfffffff0; + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, old + 1); + dns_test_end(); +} + +ATF_TC(past_to_date); +ATF_TC_HEAD(past_to_date, tc) { + atf_tc_set_md_var(tc, "descr", "past to date"); +} +ATF_TC_BODY(past_to_date, tc) { + uint32_t old, serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2014, 3, 31); + old = dns_update_soaserial(0, dns_updatemethod_date); + set_mystdtime(2014, 4, 1); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_date); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, 2014040100); + dns_test_end(); +} + +ATF_TC(now_to_date); +ATF_TC_HEAD(now_to_date, tc) { + atf_tc_set_md_var(tc, "descr", "now to date"); +} +ATF_TC_BODY(now_to_date, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2014, 4, 1); + old = dns_update_soaserial(0, dns_updatemethod_date); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_date); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, 2014040101); + dns_test_end(); +} + +ATF_TC(future_to_date); +ATF_TC_HEAD(future_to_date, tc) { + atf_tc_set_md_var(tc, "descr", "future to date"); +} +ATF_TC_BODY(future_to_date, tc) { + uint32_t old; + uint32_t serial; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2014, 4, 1); + old = dns_update_soaserial(0, dns_updatemethod_date); + set_mystdtime(2014, 3, 31); + + result = dns_test_begin(NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + serial = dns_update_soaserial(old, dns_updatemethod_date); + ATF_REQUIRE_EQ(isc_serial_lt(old, serial), true); + ATF_CHECK(serial != 0); + ATF_REQUIRE_EQ(serial, 2014040101); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, increment); + ATF_TP_ADD_TC(tp, increment_past_zero); + ATF_TP_ADD_TC(tp, past_to_unix); + ATF_TP_ADD_TC(tp, now_to_unix); + ATF_TP_ADD_TC(tp, future_to_unix); + ATF_TP_ADD_TC(tp, undefined_to_unix); + ATF_TP_ADD_TC(tp, undefined_plus1_to_unix); + ATF_TP_ADD_TC(tp, undefined_minus1_to_unix); + ATF_TP_ADD_TC(tp, unixtime_zero); + ATF_TP_ADD_TC(tp, past_to_date); + ATF_TP_ADD_TC(tp, now_to_date); + ATF_TP_ADD_TC(tp, future_to_date); + + return (atf_no_error()); +} + diff --git a/lib/dns/tests/zonemgr_test.c b/lib/dns/tests/zonemgr_test.c new file mode 100644 index 0000000..03079c6 --- /dev/null +++ b/lib/dns/tests/zonemgr_test.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> + +#include <isc/buffer.h> +#include <isc/task.h> +#include <isc/timer.h> + +#include <dns/name.h> +#include <dns/view.h> +#include <dns/zone.h> + +#include "dnstest.h" + +/* + * Individual unit tests + */ +ATF_TC(zonemgr_create); +ATF_TC_HEAD(zonemgr_create, tc) { + atf_tc_set_md_var(tc, "descr", "create zone manager"); +} +ATF_TC_BODY(zonemgr_create, tc) { + dns_zonemgr_t *myzonemgr = NULL; + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr, + &myzonemgr); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_zonemgr_shutdown(myzonemgr); + dns_zonemgr_detach(&myzonemgr); + ATF_REQUIRE_EQ(myzonemgr, NULL); + + dns_test_end(); +} + + +ATF_TC(zonemgr_managezone); +ATF_TC_HEAD(zonemgr_managezone, tc) { + atf_tc_set_md_var(tc, "descr", "manage and release a zone"); +} +ATF_TC_BODY(zonemgr_managezone, tc) { + dns_zonemgr_t *myzonemgr = NULL; + dns_zone_t *zone = NULL; + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr, + &myzonemgr); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_makezone("foo", &zone, NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* This should not succeed until the dns_zonemgr_setsize() is run */ + result = dns_zonemgr_managezone(myzonemgr, zone); + ATF_REQUIRE_EQ(result, ISC_R_FAILURE); + + ATF_REQUIRE_EQ(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 0); + + result = dns_zonemgr_setsize(myzonemgr, 1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Now it should succeed */ + result = dns_zonemgr_managezone(myzonemgr, zone); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 1); + + dns_zonemgr_releasezone(myzonemgr, zone); + dns_zone_detach(&zone); + + ATF_REQUIRE_EQ(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 0); + + dns_zonemgr_shutdown(myzonemgr); + dns_zonemgr_detach(&myzonemgr); + ATF_REQUIRE_EQ(myzonemgr, NULL); + + dns_test_end(); +} + +ATF_TC(zonemgr_createzone); +ATF_TC_HEAD(zonemgr_createzone, tc) { + atf_tc_set_md_var(tc, "descr", "create and release a zone"); +} +ATF_TC_BODY(zonemgr_createzone, tc) { + dns_zonemgr_t *myzonemgr = NULL; + dns_zone_t *zone = NULL; + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr, + &myzonemgr); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* This should not succeed until the dns_zonemgr_setsize() is run */ + result = dns_zonemgr_createzone(myzonemgr, &zone); + ATF_REQUIRE_EQ(result, ISC_R_FAILURE); + + result = dns_zonemgr_setsize(myzonemgr, 1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Now it should succeed */ + result = dns_zonemgr_createzone(myzonemgr, &zone); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(zone != NULL); + + if (zone != NULL) + dns_zone_detach(&zone); + + dns_zonemgr_shutdown(myzonemgr); + dns_zonemgr_detach(&myzonemgr); + ATF_REQUIRE_EQ(myzonemgr, NULL); + + dns_test_end(); +} + +ATF_TC(zonemgr_unreachable); +ATF_TC_HEAD(zonemgr_unreachable, tc) { + atf_tc_set_md_var(tc, "descr", "manage and release a zone"); +} +ATF_TC_BODY(zonemgr_unreachable, tc) { + dns_zonemgr_t *myzonemgr = NULL; + dns_zone_t *zone = NULL; + isc_sockaddr_t addr1, addr2; + struct in_addr in; + isc_result_t result; + isc_time_t now; + + UNUSED(tc); + + TIME_NOW(&now); + + result = dns_test_begin(NULL, true); + + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr, + &myzonemgr); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_makezone("foo", &zone, NULL, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_zonemgr_setsize(myzonemgr, 1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_zonemgr_managezone(myzonemgr, zone); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + in.s_addr = inet_addr("10.53.0.1"); + isc_sockaddr_fromin(&addr1, &in, 2112); + in.s_addr = inet_addr("10.53.0.2"); + isc_sockaddr_fromin(&addr2, &in, 5150); + ATF_CHECK(! dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + /* + * We require multiple unreachableadd calls to mark a server as + * unreachable. + */ + dns_zonemgr_unreachableadd(myzonemgr, &addr1, &addr2, &now); + ATF_CHECK(! dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + dns_zonemgr_unreachableadd(myzonemgr, &addr1, &addr2, &now); + ATF_CHECK(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + + in.s_addr = inet_addr("10.53.0.3"); + isc_sockaddr_fromin(&addr2, &in, 5150); + ATF_CHECK(! dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + /* + * We require multiple unreachableadd calls to mark a server as + * unreachable. + */ + dns_zonemgr_unreachableadd(myzonemgr, &addr1, &addr2, &now); + dns_zonemgr_unreachableadd(myzonemgr, &addr1, &addr2, &now); + ATF_CHECK(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + + dns_zonemgr_unreachabledel(myzonemgr, &addr1, &addr2); + ATF_CHECK(! dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + + in.s_addr = inet_addr("10.53.0.2"); + isc_sockaddr_fromin(&addr2, &in, 5150); + ATF_CHECK(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + dns_zonemgr_unreachabledel(myzonemgr, &addr1, &addr2); + ATF_CHECK(! dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + + dns_zonemgr_releasezone(myzonemgr, zone); + dns_zone_detach(&zone); + dns_zonemgr_shutdown(myzonemgr); + dns_zonemgr_detach(&myzonemgr); + ATF_REQUIRE_EQ(myzonemgr, NULL); + + dns_test_end(); +} + + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, zonemgr_create); + ATF_TP_ADD_TC(tp, zonemgr_managezone); + ATF_TP_ADD_TC(tp, zonemgr_createzone); + ATF_TP_ADD_TC(tp, zonemgr_unreachable); + return (atf_no_error()); +} + +/* + * XXX: + * dns_zonemgr API calls that are not yet part of this unit test: + * + * - dns_zonemgr_attach + * - dns_zonemgr_forcemaint + * - dns_zonemgr_resumexfrs + * - dns_zonemgr_shutdown + * - dns_zonemgr_setsize + * - dns_zonemgr_settransfersin + * - dns_zonemgr_getttransfersin + * - dns_zonemgr_settransfersperns + * - dns_zonemgr_getttransfersperns + * - dns_zonemgr_setiolimit + * - dns_zonemgr_getiolimit + * - dns_zonemgr_dbdestroyed + * - dns_zonemgr_setserialqueryrate + * - dns_zonemgr_getserialqueryrate + */ diff --git a/lib/dns/tests/zt_test.c b/lib/dns/tests/zt_test.c new file mode 100644 index 0000000..d2756c2 --- /dev/null +++ b/lib/dns/tests/zt_test.c @@ -0,0 +1,342 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <stdbool.h> +#include <unistd.h> + +#include <isc/app.h> +#include <isc/buffer.h> +#include <isc/print.h> +#include <isc/task.h> +#include <isc/timer.h> + +#include <dns/db.h> +#include <dns/name.h> +#include <dns/view.h> +#include <dns/zone.h> +#include <dns/zt.h> + +#include "dnstest.h" + +struct args { + void *arg1; + void *arg2; + bool arg3; +}; + +/* + * Helper functions + */ +static isc_result_t +count_zone(dns_zone_t *zone, void *uap) { + int *nzones = (int *)uap; + + UNUSED(zone); + + *nzones += 1; + return (ISC_R_SUCCESS); +} + +static isc_result_t +load_done(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) { + /* We treat zt as a pointer to a boolean for testing purposes */ + bool *done = (bool *) zt; + + UNUSED(zone); + UNUSED(task); + + *done = true; + isc_app_shutdown(); + return (ISC_R_SUCCESS); +} + +static isc_result_t +all_done(void *arg) { + bool *done = (bool *) arg; + + *done = true; + isc_app_shutdown(); + return (ISC_R_SUCCESS); +} + +static void +start_zt_asyncload(isc_task_t *task, isc_event_t *event) { + struct args *args = (struct args *)(event->ev_arg); + + UNUSED(task); + + dns_zt_asyncload2(args->arg1, all_done, args->arg2, false); + + isc_event_free(&event); +} + +static void +start_zone_asyncload(isc_task_t *task, isc_event_t *event) { + struct args *args = (struct args *)(event->ev_arg); + + UNUSED(task); + + dns_zone_asyncload2(args->arg1, load_done, args->arg2, args->arg3); + isc_event_free(&event); +} + +/* + * Individual unit tests + */ +ATF_TC(apply); +ATF_TC_HEAD(apply, tc) { + atf_tc_set_md_var(tc, "descr", "apply a function to a zone table"); +} +ATF_TC_BODY(apply, tc) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_view_t *view = NULL; + int nzones = 0; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_makezone("foo", &zone, NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + view = dns_zone_getview(zone); + ATF_REQUIRE(view->zonetable != NULL); + + ATF_CHECK_EQ(0, nzones); + result = dns_zt_apply(view->zonetable, false, count_zone, &nzones); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK_EQ(1, nzones); + + /* These steps are necessary so the zone can be detached properly */ + result = dns_test_setupzonemgr(); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_test_releasezone(zone); + dns_test_closezonemgr(); + + /* The view was left attached in dns_test_makezone() */ + dns_view_detach(&view); + dns_zone_detach(&zone); + + dns_test_end(); +} + +ATF_TC(asyncload_zone); +ATF_TC_HEAD(asyncload_zone, tc) { + atf_tc_set_md_var(tc, "descr", "asynchronous zone load"); +} +ATF_TC_BODY(asyncload_zone, tc) { + isc_result_t result; + int n; + dns_zone_t *zone = NULL; + dns_view_t *view = NULL; + dns_db_t *db = NULL; + FILE* zonefile, *origfile; + char buf[4096]; + bool done = false; + int i = 0; + struct args args; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_makezone("foo", &zone, NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_setupzonemgr(); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + view = dns_zone_getview(zone); + ATF_REQUIRE(view->zonetable != NULL); + + ATF_CHECK(!dns__zone_loadpending(zone)); + ATF_CHECK(!done); + zonefile = fopen("./zone.data", "wb"); + ATF_CHECK(zonefile != NULL); + origfile = fopen("./testdata/zt/zone1.db", "r+b"); + ATF_CHECK(origfile != NULL); + n = fread(buf, 1, 4096, origfile); + fclose(origfile); + fwrite(buf, 1, n, zonefile); + fflush(zonefile); + + dns_zone_setfile(zone, "./zone.data"); + + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + while (dns__zone_loadpending(zone) && i++ < 5000) + dns_test_nap(1000); + ATF_CHECK(done); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + dns_db_detach(&db); + /* + * Add something to zone file, reload zone with newonly - it should + * not be reloaded. + */ + fprintf(zonefile, "\nb in b 1.2.3.4\n"); + fflush(zonefile); + fclose(zonefile); + + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + + while (dns__zone_loadpending(zone) && i++ < 5000) + dns_test_nap(1000); + ATF_CHECK(done); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + dns_db_detach(&db); + + /* Now reload it without newonly - it should be reloaded */ + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + + while (dns__zone_loadpending(zone) && i++ < 5000) + dns_test_nap(1000); + ATF_CHECK(done); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + + ATF_CHECK(db != NULL); + if (db != NULL) + dns_db_detach(&db); + + dns_test_releasezone(zone); + dns_test_closezonemgr(); + + dns_zone_detach(&zone); + dns_view_detach(&view); + + dns_test_end(); +} + +ATF_TC(asyncload_zt); +ATF_TC_HEAD(asyncload_zt, tc) { + atf_tc_set_md_var(tc, "descr", "asynchronous zone table load"); +} +ATF_TC_BODY(asyncload_zt, tc) { + isc_result_t result; + dns_zone_t *zone1 = NULL, *zone2 = NULL, *zone3 = NULL; + dns_view_t *view; + dns_zt_t *zt; + dns_db_t *db = NULL; + bool done = false; + int i = 0; + struct args args; + + UNUSED(tc); + + result = dns_test_begin(NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_makezone("foo", &zone1, NULL, true); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_zone_setfile(zone1, "testdata/zt/zone1.db"); + view = dns_zone_getview(zone1); + + result = dns_test_makezone("bar", &zone2, view, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_zone_setfile(zone2, "testdata/zt/zone1.db"); + + /* This one will fail to load */ + result = dns_test_makezone("fake", &zone3, view, false); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + dns_zone_setfile(zone3, "testdata/zt/nonexistent.db"); + + zt = view->zonetable; + ATF_REQUIRE(zt != NULL); + + result = dns_test_setupzonemgr(); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone2); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone3); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_CHECK(!dns__zone_loadpending(zone1)); + ATF_CHECK(!dns__zone_loadpending(zone2)); + ATF_CHECK(!done); + + args.arg1 = zt; + args.arg2 = &done; + isc_app_onrun(mctx, maintask, start_zt_asyncload, &args); + + isc_app_run(); + while (!done && i++ < 5000) + dns_test_nap(1000); + ATF_CHECK(done); + + /* Both zones should now be loaded; test them */ + result = dns_zone_getdb(zone1, &db); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(db != NULL); + if (db != NULL) + dns_db_detach(&db); + + result = dns_zone_getdb(zone2, &db); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(db != NULL); + if (db != NULL) + dns_db_detach(&db); + + dns_test_releasezone(zone3); + dns_test_releasezone(zone2); + dns_test_releasezone(zone1); + dns_test_closezonemgr(); + + dns_zone_detach(&zone1); + dns_zone_detach(&zone2); + dns_zone_detach(&zone3); + dns_view_detach(&view); + + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, apply); + ATF_TP_ADD_TC(tp, asyncload_zone); + ATF_TP_ADD_TC(tp, asyncload_zt); + return (atf_no_error()); +} |