diff --git a/CHANGES b/CHANGES index ee2025ff43..d6dee6a332 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +4667. [cleanup] Refactor RDATA unit tests. [RT #45610] + 4666. [bug] dnssec-keymgr: Domain names beginning with digits (0-9) could cause a parser error when reading the policy file. This now works correctly so long as the domain diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in index 533683090d..e80ad0be23 100644 --- a/bin/tests/Makefile.in +++ b/bin/tests/Makefile.in @@ -71,7 +71,6 @@ XTARGETS = adb_test@EXEEXT@ \ nsecify@EXEEXT@ \ ratelimiter_test@EXEEXT@ \ rbt_test@EXEEXT@ \ - rdata_test@EXEEXT@ \ rwlock_test@EXEEXT@ \ serial_test@EXEEXT@ \ shutdown_test@EXEEXT@ \ @@ -110,7 +109,6 @@ XSRCS = adb_test.c \ nsecify.c \ ratelimiter_test.c \ rbt_test.c \ - rdata_test.c \ rwlock_test.c \ serial_test.c \ shutdown_test.c \ @@ -228,10 +226,6 @@ rbt_test@EXEEXT@: rbt_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rbt_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} -rdata_test@EXEEXT@: rdata_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rdata_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} - rwlock_test@EXEEXT@: rwlock_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rwlock_test.@O@ \ ${ISCLIBS} ${LIBS} diff --git a/bin/tests/rdata_test.c b/bin/tests/rdata_test.c deleted file mode 100644 index 7156114c10..0000000000 --- a/bin/tests/rdata_test.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* - * Copyright (C) 1998-2007, 2011, 2012, 2014-2017 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/. - */ - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -isc_lexspecials_t specials; - -static void -viastruct(dns_rdata_t *rdata, isc_mem_t *mctx, - dns_rdata_t *rdata2, isc_buffer_t *b) -{ - isc_result_t result; - void *sp = NULL; - isc_boolean_t need_free = ISC_FALSE; - dns_rdatatype_t rdt; - dns_rdataclass_t rdc; - - UNUSED(rdata2); /* XXXMPA remove when fromstruct is ready. */ - UNUSED(b); - - switch (rdata->type) { - case dns_rdatatype_a6: { - static dns_rdata_in_a6_t in_a6; - result = dns_rdata_tostruct(rdata, sp = &in_a6, NULL); - break; - } - case dns_rdatatype_a: { - switch (rdata->rdclass) { - case dns_rdataclass_hs: { - static dns_rdata_hs_a_t hs_a; - result = dns_rdata_tostruct(rdata, sp = &hs_a, NULL); - break; - } - case dns_rdataclass_in: { - static dns_rdata_in_a_t in_a; - result = dns_rdata_tostruct(rdata, sp = &in_a, NULL); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } - break; - } - case dns_rdatatype_aaaa: { - static dns_rdata_in_aaaa_t in_aaaa; - result = dns_rdata_tostruct(rdata, sp = &in_aaaa, NULL); - break; - } - case dns_rdatatype_afsdb: { - static dns_rdata_afsdb_t afsdb; - result = dns_rdata_tostruct(rdata, sp = &afsdb, NULL); - break; - } - case dns_rdatatype_any: { - result = ISC_R_NOTIMPLEMENTED; - break; - } - case dns_rdatatype_apl: { - switch (rdata->rdclass) { - case dns_rdataclass_in: { - static dns_rdata_in_apl_t in_apl; - result = dns_rdata_tostruct(rdata, sp = &in_apl, NULL); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } - break; - } - case dns_rdatatype_cert: { - static dns_rdata_cert_t cert; - result = dns_rdata_tostruct(rdata, sp = &cert, NULL); - break; - } - case dns_rdatatype_cname: { - static dns_rdata_cname_t cname; - result = dns_rdata_tostruct(rdata, sp = &cname, NULL); - break; - } - case dns_rdatatype_dname: { - static dns_rdata_dname_t dname; - result = dns_rdata_tostruct(rdata, sp = &dname, NULL); - break; - } - case dns_rdatatype_gpos: { - static dns_rdata_gpos_t gpos; - result = dns_rdata_tostruct(rdata, sp = &gpos, NULL); - break; - } - case dns_rdatatype_hinfo: { - static dns_rdata_hinfo_t hinfo; - result = dns_rdata_tostruct(rdata, sp = &hinfo, NULL); - break; - } - case dns_rdatatype_isdn: { - static dns_rdata_isdn_t isdn; - result = dns_rdata_tostruct(rdata, sp = &isdn, NULL); - break; - } - case dns_rdatatype_key: { - static dns_rdata_key_t key; - result = dns_rdata_tostruct(rdata, sp = &key, NULL); - break; - } - case dns_rdatatype_kx: { - static dns_rdata_in_kx_t in_kx; - result = dns_rdata_tostruct(rdata, sp = &in_kx, NULL); - break; - } - case dns_rdatatype_loc: { - static dns_rdata_loc_t loc; - result = dns_rdata_tostruct(rdata, sp = &loc, NULL); - break; - } - case dns_rdatatype_mb: { - static dns_rdata_mb_t mb; - result = dns_rdata_tostruct(rdata, sp = &mb, NULL); - break; - } - case dns_rdatatype_md: { - static dns_rdata_md_t md; - result = dns_rdata_tostruct(rdata, sp = &md, NULL); - break; - } - case dns_rdatatype_mf: { - static dns_rdata_mf_t mf; - result = dns_rdata_tostruct(rdata, sp = &mf, NULL); - break; - } - case dns_rdatatype_mg: { - static dns_rdata_mg_t mg; - result = dns_rdata_tostruct(rdata, sp = &mg, NULL); - break; - } - case dns_rdatatype_minfo: { - static dns_rdata_minfo_t minfo; - result = dns_rdata_tostruct(rdata, sp = &minfo, NULL); - break; - } - case dns_rdatatype_mr: { - static dns_rdata_mr_t mr; - result = dns_rdata_tostruct(rdata, sp = &mr, NULL); - break; - } - case dns_rdatatype_mx: { - static dns_rdata_mx_t mx; - result = dns_rdata_tostruct(rdata, sp = &mx, NULL); - break; - } - case dns_rdatatype_naptr: { - static dns_rdata_naptr_t naptr; - result = dns_rdata_tostruct(rdata, sp = &naptr, NULL); - break; - } - case dns_rdatatype_ns: { - static dns_rdata_ns_t ns; - result = dns_rdata_tostruct(rdata, sp = &ns, NULL); - break; - } - case dns_rdatatype_nsap: { - static dns_rdata_in_nsap_t in_nsap; - result = dns_rdata_tostruct(rdata, sp = &in_nsap, NULL); - break; - } - case dns_rdatatype_nsap_ptr: { - static dns_rdata_in_nsap_ptr_t in_nsap_ptr; - result = dns_rdata_tostruct(rdata, sp = &in_nsap_ptr, NULL); - break; - } - case dns_rdatatype_null: { - static dns_rdata_null_t null; - result = dns_rdata_tostruct(rdata, sp = &null, NULL); - break; - } - case dns_rdatatype_nxt: { - static dns_rdata_nxt_t nxt; - result = dns_rdata_tostruct(rdata, sp = &nxt, NULL); - break; - } - case dns_rdatatype_opt: { - static dns_rdata_opt_t opt; - result = dns_rdata_tostruct(rdata, sp = &opt, NULL); - break; - } - case dns_rdatatype_ptr: { - static dns_rdata_ptr_t ptr; - result = dns_rdata_tostruct(rdata, sp = &ptr, NULL); - break; - } - case dns_rdatatype_px: { - static dns_rdata_in_px_t in_px; - result = dns_rdata_tostruct(rdata, sp = &in_px, NULL); - break; - } - case dns_rdatatype_rp: { - static dns_rdata_rp_t rp; - result = dns_rdata_tostruct(rdata, sp = &rp, NULL); - break; - } - case dns_rdatatype_rt: { - static dns_rdata_rt_t rt; - result = dns_rdata_tostruct(rdata, sp = &rt, NULL); - break; - } - case dns_rdatatype_sig: { - static dns_rdata_sig_t sig; - result = dns_rdata_tostruct(rdata, sp = &sig, NULL); - break; - } - case dns_rdatatype_soa: { - static dns_rdata_soa_t soa; - result = dns_rdata_tostruct(rdata, sp = &soa, NULL); - break; - } - case dns_rdatatype_srv: { - static dns_rdata_in_srv_t in_srv; - result = dns_rdata_tostruct(rdata, sp = &in_srv, NULL); - break; - } - case dns_rdatatype_tkey: { - static dns_rdata_tkey_t tkey; - result = dns_rdata_tostruct(rdata, sp = &tkey, NULL); - break; - } - case dns_rdatatype_tsig: { - static dns_rdata_any_tsig_t tsig; - result = dns_rdata_tostruct(rdata, sp = &tsig, NULL); - break; - } - case dns_rdatatype_txt: { - static dns_rdata_txt_t txt; - result = dns_rdata_tostruct(rdata, sp = &txt, NULL); - break; - } - case dns_rdatatype_spf: { - static dns_rdata_spf_t spf; - result = dns_rdata_tostruct(rdata, sp = &spf, NULL); - break; - } - case dns_rdatatype_unspec: { - static dns_rdata_unspec_t unspec; - result = dns_rdata_tostruct(rdata, sp = &unspec, NULL); - break; - } - case dns_rdatatype_uri: { - static dns_rdata_uri_t uri; - result = dns_rdata_tostruct(rdata, sp = &uri, NULL); - break; - } - case dns_rdatatype_caa: { - static dns_rdata_caa_t caa; - result = dns_rdata_tostruct(rdata, sp = &caa, NULL); - break; - } - case dns_rdatatype_wks: { - static dns_rdata_in_wks_t in_wks; - result = dns_rdata_tostruct(rdata, sp = &in_wks, NULL); - break; - } - case dns_rdatatype_x25: { - static dns_rdata_x25_t x25; - result = dns_rdata_tostruct(rdata, sp = &x25, NULL); - break; - } - case dns_rdatatype_nsec: { - static dns_rdata_nsec_t nsec; - result = dns_rdata_tostruct(rdata, sp = &nsec, NULL); - break; - } - case dns_rdatatype_rrsig: { - static dns_rdata_rrsig_t rrsig; - result = dns_rdata_tostruct(rdata, sp = &rrsig, NULL); - break; - } - case dns_rdatatype_dnskey: { - static dns_rdata_dnskey_t dnskey; - result = dns_rdata_tostruct(rdata, sp = &dnskey, NULL); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } - if (result != ISC_R_SUCCESS) - fprintf(stdout, "viastruct: tostruct %d %d return %s\n", - rdata->type, rdata->rdclass, - dns_result_totext(result)); - else - dns_rdata_freestruct(sp); - - switch (rdata->type) { - case dns_rdatatype_a6: { - static dns_rdata_in_a6_t in_a6; - result = dns_rdata_tostruct(rdata, sp = &in_a6, mctx); - break; - } - case dns_rdatatype_a: { - switch (rdata->rdclass) { - case dns_rdataclass_hs: { - static dns_rdata_hs_a_t hs_a; - result = dns_rdata_tostruct(rdata, sp = &hs_a, mctx); - break; - } - case dns_rdataclass_in: { - static dns_rdata_in_a_t in_a; - result = dns_rdata_tostruct(rdata, sp = &in_a, mctx); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } - break; - } - case dns_rdatatype_aaaa: { - static dns_rdata_in_aaaa_t in_aaaa; - result = dns_rdata_tostruct(rdata, sp = &in_aaaa, mctx); - break; - } - case dns_rdatatype_afsdb: { - static dns_rdata_afsdb_t afsdb; - result = dns_rdata_tostruct(rdata, sp = &afsdb, mctx); - break; - } - case dns_rdatatype_any: { - result = ISC_R_NOTIMPLEMENTED; - break; - } - case dns_rdatatype_apl: { - switch (rdata->rdclass) { - case dns_rdataclass_in: { - static dns_rdata_in_apl_t in_apl; - result = dns_rdata_tostruct(rdata, sp = &in_apl, mctx); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } - break; - } - case dns_rdatatype_cert: { - static dns_rdata_cert_t cert; - result = dns_rdata_tostruct(rdata, sp = &cert, mctx); - break; - } - case dns_rdatatype_cname: { - static dns_rdata_cname_t cname; - result = dns_rdata_tostruct(rdata, sp = &cname, mctx); - break; - } - case dns_rdatatype_dname: { - static dns_rdata_dname_t dname; - result = dns_rdata_tostruct(rdata, sp = &dname, mctx); - break; - } - case dns_rdatatype_gpos: { - static dns_rdata_gpos_t gpos; - result = dns_rdata_tostruct(rdata, sp = &gpos, mctx); - break; - } - case dns_rdatatype_hinfo: { - static dns_rdata_hinfo_t hinfo; - result = dns_rdata_tostruct(rdata, sp = &hinfo, mctx); - break; - } - case dns_rdatatype_isdn: { - static dns_rdata_isdn_t isdn; - result = dns_rdata_tostruct(rdata, sp = &isdn, mctx); - break; - } - case dns_rdatatype_key: { - static dns_rdata_key_t key; - result = dns_rdata_tostruct(rdata, sp = &key, mctx); - break; - } - case dns_rdatatype_kx: { - static dns_rdata_in_kx_t in_kx; - result = dns_rdata_tostruct(rdata, sp = &in_kx, mctx); - break; - } - case dns_rdatatype_loc: { - static dns_rdata_loc_t loc; - result = dns_rdata_tostruct(rdata, sp = &loc, mctx); - break; - } - case dns_rdatatype_mb: { - static dns_rdata_mb_t mb; - result = dns_rdata_tostruct(rdata, sp = &mb, mctx); - break; - } - case dns_rdatatype_md: { - static dns_rdata_md_t md; - result = dns_rdata_tostruct(rdata, sp = &md, mctx); - break; - } - case dns_rdatatype_mf: { - static dns_rdata_mf_t mf; - result = dns_rdata_tostruct(rdata, sp = &mf, mctx); - break; - } - case dns_rdatatype_mg: { - static dns_rdata_mg_t mg; - result = dns_rdata_tostruct(rdata, sp = &mg, mctx); - break; - } - case dns_rdatatype_minfo: { - static dns_rdata_minfo_t minfo; - result = dns_rdata_tostruct(rdata, sp = &minfo, mctx); - break; - } - case dns_rdatatype_mr: { - static dns_rdata_mr_t mr; - result = dns_rdata_tostruct(rdata, sp = &mr, mctx); - break; - } - case dns_rdatatype_mx: { - static dns_rdata_mx_t mx; - result = dns_rdata_tostruct(rdata, sp = &mx, mctx); - break; - } - case dns_rdatatype_naptr: { - static dns_rdata_naptr_t naptr; - result = dns_rdata_tostruct(rdata, sp = &naptr, mctx); - break; - } - case dns_rdatatype_ns: { - static dns_rdata_ns_t ns; - result = dns_rdata_tostruct(rdata, sp = &ns, mctx); - break; - } - case dns_rdatatype_nsap: { - static dns_rdata_in_nsap_t in_nsap; - result = dns_rdata_tostruct(rdata, sp = &in_nsap, mctx); - break; - } - case dns_rdatatype_nsap_ptr: { - static dns_rdata_in_nsap_ptr_t in_nsap_ptr; - result = dns_rdata_tostruct(rdata, sp = &in_nsap_ptr, mctx); - break; - } - case dns_rdatatype_null: { - static dns_rdata_null_t null; - result = dns_rdata_tostruct(rdata, sp = &null, mctx); - break; - } - case dns_rdatatype_nxt: { - static dns_rdata_nxt_t nxt; - result = dns_rdata_tostruct(rdata, sp = &nxt, mctx); - break; - } - case dns_rdatatype_opt: { - static dns_rdata_opt_t opt; - result = dns_rdata_tostruct(rdata, sp = &opt, mctx); - break; - } - case dns_rdatatype_ptr: { - static dns_rdata_ptr_t ptr; - result = dns_rdata_tostruct(rdata, sp = &ptr, mctx); - break; - } - case dns_rdatatype_px: { - static dns_rdata_in_px_t in_px; - result = dns_rdata_tostruct(rdata, sp = &in_px, mctx); - break; - } - case dns_rdatatype_rp: { - static dns_rdata_rp_t rp; - result = dns_rdata_tostruct(rdata, sp = &rp, mctx); - break; - } - case dns_rdatatype_rt: { - static dns_rdata_rt_t rt; - result = dns_rdata_tostruct(rdata, sp = &rt, mctx); - break; - } - case dns_rdatatype_sig: { - static dns_rdata_sig_t sig; - result = dns_rdata_tostruct(rdata, sp = &sig, mctx); - break; - } - case dns_rdatatype_soa: { - static dns_rdata_soa_t soa; - result = dns_rdata_tostruct(rdata, sp = &soa, mctx); - break; - } - case dns_rdatatype_srv: { - static dns_rdata_in_srv_t in_srv; - result = dns_rdata_tostruct(rdata, sp = &in_srv, mctx); - break; - } - case dns_rdatatype_tkey: { - static dns_rdata_tkey_t tkey; - result = dns_rdata_tostruct(rdata, sp = &tkey, mctx); - break; - } - case dns_rdatatype_tsig: { - static dns_rdata_any_tsig_t tsig; - result = dns_rdata_tostruct(rdata, sp = &tsig, mctx); - break; - } - case dns_rdatatype_txt: { - static dns_rdata_txt_t txt; - result = dns_rdata_tostruct(rdata, sp = &txt, mctx); - break; - } - case dns_rdatatype_spf: { - static dns_rdata_spf_t spf; - result = dns_rdata_tostruct(rdata, sp = &spf, mctx); - break; - } - case dns_rdatatype_unspec: { - static dns_rdata_unspec_t unspec; - result = dns_rdata_tostruct(rdata, sp = &unspec, mctx); - break; - } - case dns_rdatatype_uri: { - static dns_rdata_uri_t uri; - result = dns_rdata_tostruct(rdata, sp = &uri, mctx); - break; - } - case dns_rdatatype_caa: { - static dns_rdata_caa_t caa; - result = dns_rdata_tostruct(rdata, sp = &caa, mctx); - break; - } - case dns_rdatatype_wks: { - static dns_rdata_in_wks_t in_wks; - result = dns_rdata_tostruct(rdata, sp = &in_wks, mctx); - break; - } - case dns_rdatatype_x25: { - static dns_rdata_x25_t x25; - result = dns_rdata_tostruct(rdata, sp = &x25, mctx); - break; - } - case dns_rdatatype_nsec: { - static dns_rdata_nsec_t nsec; - result = dns_rdata_tostruct(rdata, sp = &nsec, mctx); - break; - } - case dns_rdatatype_rrsig: { - static dns_rdata_rrsig_t rrsig; - result = dns_rdata_tostruct(rdata, sp = &rrsig, mctx); - break; - } - case dns_rdatatype_dnskey: { - static dns_rdata_dnskey_t dnskey; - result = dns_rdata_tostruct(rdata, sp = &dnskey, mctx); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } - if (result != ISC_R_SUCCESS) - fprintf(stdout, "viastruct: tostruct %d %d return %s\n", - rdata->type, rdata->rdclass, - dns_result_totext(result)); - else { - need_free = ISC_TRUE; - - rdc = rdata->rdclass; - rdt = rdata->type; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, sp, b); - if (result != ISC_R_SUCCESS) - fprintf(stdout, - "viastruct: fromstruct %d %d return %s\n", - rdata->type, rdata->rdclass, - dns_result_totext(result)); - else if (rdata->length != rdata2->length || - memcmp(rdata->data, rdata2->data, rdata->length) != 0) - { - isc_uint32_t i; - isc_uint32_t l; - - fprintf(stdout, "viastruct: memcmp failed\n"); - - fprintf(stdout, "%d %d\n", - rdata->length, rdata2->length); - l = rdata->length; - if (rdata2->length < l) - l = rdata2->length; - for (i = 0; i < l; i++) - fprintf(stdout, "%02x %02x\n", - rdata->data[i], rdata2->data[i]); - } - } -#if 0 - switch (rdata->type) { - case dns_rdatatype_a6: { - dns_rdata_in_a6_t in_a6; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_a6, b); - break; - } - case dns_rdatatype_a: { - switch (rdata->rdclass) { - case dns_rdataclass_hs: { - dns_rdata_hs_a_t hs_a; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, - &hs_a, b); - break; - } - case dns_rdataclass_in: { - dns_rdata_in_a_t in_a; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, - &in_a, b); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } - break; - } - case dns_rdatatype_aaaa: { - dns_rdata_in_aaaa_t in_aaaa; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_aaaa, b); - break; - } - case dns_rdatatype_afsdb: { - dns_rdata_afsdb_t afsdb; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &afsdb, b); - break; - } - case dns_rdatatype_any: { - result = ISC_R_NOTIMPLEMENTED; - break; - } - case dns_rdatatype_apl: { - switch (rdata->rdclass) { - case dns_rdataclass_in: { - dns_rdata_in_apl_t in_apl; - result = dns_rdata_fromstruct(rdata, rdc, rdt, &in_apl, b); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } - break; - } - case dns_rdatatype_cert: { - dns_rdata_cert_t cert; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &cert, b); - break; - } - case dns_rdatatype_cname: { - dns_rdata_cname_t cname; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &cname, b); - break; - } - case dns_rdatatype_dname: { - dns_rdata_dname_t dname; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &dname, b); - break; - } - case dns_rdatatype_gpos: { - dns_rdata_gpos_t gpos; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &gpos, b); - break; - } - case dns_rdatatype_hinfo: { - dns_rdata_hinfo_t hinfo; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &hinfo, b); - break; - } - case dns_rdatatype_isdn: { - dns_rdata_isdn_t isdn; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &isdn, b); - break; - } - case dns_rdatatype_key: { - dns_rdata_key_t key; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &key, b); - break; - } - case dns_rdatatype_kx: { - dns_rdata_in_kx_t in_kx; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_kx, b); - break; - } - case dns_rdatatype_loc: { - dns_rdata_loc_t loc; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &loc, b); - break; - } - case dns_rdatatype_mb: { - dns_rdata_mb_t mb; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mb, b); - break; - } - case dns_rdatatype_md: { - dns_rdata_md_t md; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &md, b); - break; - } - case dns_rdatatype_mf: { - dns_rdata_mf_t mf; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mf, b); - break; - } - case dns_rdatatype_mg: { - dns_rdata_mg_t mg; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mg, b); - break; - } - case dns_rdatatype_minfo: { - dns_rdata_minfo_t minfo; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &minfo, b); - break; - } - case dns_rdatatype_mr: { - dns_rdata_mr_t mr; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mr, b); - break; - } - case dns_rdatatype_mx: { - dns_rdata_mx_t mx; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mx, b); - break; - } - case dns_rdatatype_naptr: { - dns_rdata_naptr_t naptr; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &naptr, b); - break; - } - case dns_rdatatype_ns: { - dns_rdata_ns_t ns; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &ns, b); - break; - } - case dns_rdatatype_nsap: { - dns_rdata_in_nsap_t in_nsap; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_nsap, b); - break; - } - case dns_rdatatype_nsap_ptr: { - dns_rdata_in_nsap_ptr_t in_nsap_ptr; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_nsap_ptr, - b); - break; - } - case dns_rdatatype_null: { - dns_rdata_null_t null; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &null, b); - break; - } - case dns_rdatatype_nxt: { - dns_rdata_nxt_t nxt; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &nxt, b); - break; - } - case dns_rdatatype_opt: { - dns_rdata_opt_t opt; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &opt, b); - break; - } - case dns_rdatatype_ptr: { - dns_rdata_ptr_t ptr; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &ptr, b); - break; - } - case dns_rdatatype_px: { - dns_rdata_in_px_t in_px; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_px, b); - break; - } - case dns_rdatatype_rp: { - dns_rdata_rp_t rp; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rp, b); - break; - } - case dns_rdatatype_rt: { - dns_rdata_rt_t rt; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rt, b); - break; - } - case dns_rdatatype_sig: { - dns_rdata_sig_t sig; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &sig, b); - break; - } - case dns_rdatatype_soa: { - dns_rdata_soa_t soa; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &soa, b); - break; - } - case dns_rdatatype_srv: { - dns_rdata_in_srv_t in_srv; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_srv, b); - break; - } - case dns_rdatatype_tkey: { - dns_rdata_tkey_t tkey; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &tkey, b); - break; - } - case dns_rdatatype_tsig: { - dns_rdata_any_tsig_t tsig; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &tsig, b); - break; - } - case dns_rdatatype_txt: { - dns_rdata_txt_t txt; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &txt, b); - break; - } - case dns_rdatatype_spf: { - dns_rdata_spf_t spf; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &spf, b); - break; - } - case dns_rdatatype_unspec: { - dns_rdata_unspec_t unspec; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &unspec, b); - break; - } - case dns_rdatatype_uri: { - dns_rdata_uri_t uri; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &uri, b); - break; - } - case dns_rdatatype_caa: { - dns_rdata_caa_t caa; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &caa, b); - break; - } - case dns_rdatatype_wks: { - dns_rdata_in_wks_t in_wks; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_wks, b); - break; - } - case dns_rdatatype_x25: { - dns_rdata_x25_t x25; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &x25, b); - break; - } - case dns_rdatatype_nsec: { - dns_rdata_nsec_t nsec; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &nsec, b); - break; - } - case dns_rdatatype_rrsig: { - dns_rdata_rrsig_t rrsig; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rrsig, b); - break; - } - case dns_rdatatype_dnskey: { - dns_rdata_dnskey_t dnskey; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &dnskey, b); - break; - } - default: - result = ISC_R_NOTIMPLEMENTED; - break; - } -#endif - if (need_free) - dns_rdata_freestruct(sp); -} - -int -main(int argc, char *argv[]) { - isc_mem_t *mctx = NULL; - isc_lex_t *lex = NULL; - isc_token_t token; - isc_result_t result; - int quiet = 0; - int c; - int stats = 0; - unsigned int options = 0; - dns_rdatatype_t type; - dns_rdataclass_t class; - dns_rdatatype_t lasttype = 0; - char outbuf[16*1024]; - char inbuf[16*1024]; - char wirebuf[16*1024]; - char viabuf[16*1024]; - isc_buffer_t dbuf; - isc_buffer_t tbuf; - isc_buffer_t wbuf; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_t last = DNS_RDATA_INIT; - int need_eol = 0; - int wire = 0; - dns_compress_t cctx; - dns_decompress_t dctx; - int trunc = 0; - int add = 0; - int len; - int zero = 0; - int debug = 0; - isc_region_t region; - int first = 1; - int raw = 0; - int tostruct = 0; - - while ((c = isc_commandline_parse(argc, argv, "dqswtarzS")) != -1) { - switch (c) { - case 'd': - debug = 1; - quiet = 0; - break; - case 'q': - quiet = 1; - debug = 0; - break; - case 's': - stats = 1; - break; - case 'w': - wire = 1; - break; - case 't': - trunc = 1; - break; - case 'a': - add = 1; - break; - case 'z': - zero = 1; - break; - case 'r': - raw++; - break; - case 'S': - tostruct++; - break; - } - } - - memset(&dctx, 0, sizeof(dctx)); - dctx.allowed = DNS_COMPRESS_ALL; - - RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); - RUNTIME_CHECK(isc_lex_create(mctx, 256, &lex) == ISC_R_SUCCESS); - - /* - * Set up to lex DNS master file. - */ - - specials['('] = 1; - specials[')'] = 1; - specials['"'] = 1; - isc_lex_setspecials(lex, specials); - options = ISC_LEXOPT_EOL; - isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); - - RUNTIME_CHECK(isc_lex_openstream(lex, stdin) == ISC_R_SUCCESS); - - dns_rdata_init(&last); - while ((result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER, - &token)) == ISC_R_SUCCESS) { - if (debug) fprintf(stdout, "token.type = %d\n", token.type); - if (need_eol) { - if (token.type == isc_tokentype_eol) - need_eol = 0; - continue; - } - if (token.type == isc_tokentype_eof) - break; - - /* - * Get type. - */ - if (token.type == isc_tokentype_number) { - type = token.value.as_ulong; - isc_buffer_init(&tbuf, outbuf, sizeof(outbuf)); - result = dns_rdatatype_totext(type, &tbuf); - if (result != ISC_R_SUCCESS) { - fprintf(stdout, - "dns_rdatatype_totext " - "returned %s(%d)\n", - dns_result_totext(result), result); - fflush(stdout); - need_eol = 1; - continue; - } - fprintf(stdout, "type = %.*s(%d)\n", - (int)tbuf.used, (char*)tbuf.base, type); - } else if (token.type == isc_tokentype_string) { - result = dns_rdatatype_fromtext(&type, - &token.value.as_textregion); - if (result != ISC_R_SUCCESS) { - fprintf(stdout, - "dns_rdatatype_fromtext " - "returned %s(%d)\n", - dns_result_totext(result), result); - fflush(stdout); - need_eol = 1; - continue; - } - fprintf(stdout, "type = %.*s(%d)\n", - (int)token.value.as_textregion.length, - token.value.as_textregion.base, type); - } else - continue; - - result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER, - &token); - if (result != ISC_R_SUCCESS) - break; - if (token.type == isc_tokentype_eol) - continue; - if (token.type == isc_tokentype_eof) - break; - if (token.type == isc_tokentype_number) { - class = token.value.as_ulong; - isc_buffer_init(&tbuf, outbuf, sizeof(outbuf)); - result = dns_rdatatype_totext(class, &tbuf); - if (result != ISC_R_SUCCESS) { - fprintf(stdout, "dns_rdatatype_totext " - "returned %s(%d)\n", - dns_result_totext(result), result); - fflush(stdout); - need_eol = 1; - continue; - } - fprintf(stdout, "class = %.*s(%d)\n", - (int)tbuf.used, (char*)tbuf.base, class); - } else if (token.type == isc_tokentype_string) { - result = dns_rdataclass_fromtext(&class, - &token.value.as_textregion); - if (result != ISC_R_SUCCESS) { - fprintf(stdout, "dns_rdataclass_fromtext " - "returned %s(%d)\n", - dns_result_totext(result), result); - fflush(stdout); - need_eol = 1; - continue; - } - fprintf(stdout, "class = %.*s(%d)\n", - (int)token.value.as_textregion.length, - token.value.as_textregion.base, class); - } else - continue; - - fflush(stdout); - dns_rdata_init(&rdata); - isc_buffer_init(&dbuf, inbuf, sizeof(inbuf)); - result = dns_rdata_fromtext(&rdata, class, type, lex, - NULL, 0, mctx, &dbuf, - NULL); - if (result != ISC_R_SUCCESS) { - fprintf(stdout, - "dns_rdata_fromtext returned %s(%d)\n", - dns_result_totext(result), result); - fflush(stdout); - continue; - } - if (raw) { - unsigned int i; - for (i = 0; i < rdata.length; /* */ ) { - fprintf(stdout, "%02x", rdata.data[i]); - if ((++i % 20) == 0) - fputs("\n", stdout); - else - if (i == rdata.length) - fputs("\n", stdout); - else - fputs(" ", stdout); - } - } - - /* - * Convert to wire and back? - */ - if (wire) { - result = dns_compress_init(&cctx, -1, mctx); - if (result != ISC_R_SUCCESS) { - fprintf(stdout, - "dns_compress_init returned %s(%d)\n", - dns_result_totext(result), result); - continue; - } - isc_buffer_init(&wbuf, wirebuf, sizeof(wirebuf)); - result = dns_rdata_towire(&rdata, &cctx, &wbuf); - dns_compress_invalidate(&cctx); - if (result != ISC_R_SUCCESS) { - fprintf(stdout, - "dns_rdata_towire returned %s(%d)\n", - dns_result_totext(result), result); - continue; - } - len = wbuf.used - wbuf.current; - if (raw > 2) { - unsigned int i; - fputs("\n", stdout); - for (i = 0; i < (unsigned int)len; /* */ ) { - fprintf(stdout, "%02x", - ((unsigned char*)wbuf.base)[i + wbuf.current]); - if ((++i % 20) == 0) - fputs("\n", stdout); - else - if (i == wbuf.used) - fputs("\n", stdout); - else - fputs(" ", stdout); - } - } - if (zero) - len = 0; - if (trunc) - len = (len * 3) / 4; - if (add) { - isc_buffer_add(&wbuf, len / 4 + 1); - len += len / 4 + 1; - } - - isc_buffer_setactive(&wbuf, len); - dns_rdata_init(&rdata); - isc_buffer_init(&dbuf, inbuf, sizeof(inbuf)); - dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); - result = dns_rdata_fromwire(&rdata, class, type, &wbuf, - &dctx, 0, &dbuf); - dns_decompress_invalidate(&dctx); - if (result != ISC_R_SUCCESS) { - fprintf(stdout, - "dns_rdata_fromwire returned %s(%d)\n", - dns_result_totext(result), result); - fflush(stdout); - continue; - } - } - if (raw > 1) { - unsigned int i; - fputs("\n", stdout); - for (i = 0; i < rdata.length; /* */ ) { - fprintf(stdout, "%02x", rdata.data[i]); - if ((++i % 20) == 0) - fputs("\n", stdout); - else - if (i == rdata.length) - fputs("\n", stdout); - else - fputs(" ", stdout); - } - } - if (tostruct) { - isc_mem_t *mctx2 = NULL; - dns_rdata_t rdata2 = DNS_RDATA_INIT; - isc_buffer_t vbuf; - - RUNTIME_CHECK(isc_mem_create(0, 0, &mctx2) - == ISC_R_SUCCESS); - - isc_buffer_init(&vbuf, viabuf, sizeof(viabuf)); - dns_rdata_init(&rdata2); - viastruct(&rdata, mctx2, &rdata2, &vbuf); - if (!quiet && stats) - isc_mem_stats(mctx2, stdout); - isc_mem_destroy(&mctx2); - } - - isc_buffer_init(&tbuf, outbuf, sizeof(outbuf)); - result = dns_rdata_totext(&rdata, NULL, &tbuf); - if (result != ISC_R_SUCCESS) - fprintf(stdout, "dns_rdata_totext returned %s(%d)\n", - dns_result_totext(result), result); - else - fprintf(stdout, "\"%.*s\"\n", - (int)tbuf.used, (char*)tbuf.base); - fflush(stdout); - if (lasttype == type) { - fprintf(stdout, "dns_rdata_compare = %d\n", - dns_rdata_compare(&rdata, &last)); - - } - if (!first) { - free(last.data); - } - dns_rdata_init(&last); - region.base = malloc(region.length = rdata.length); - if (region.base) { - memmove(region.base, rdata.data, rdata.length); - dns_rdata_fromregion(&last, class, type, ®ion); - lasttype = type; - first = 0; - } else - first = 1; - - } - if (result != ISC_R_EOF) - printf("Result: %s\n", isc_result_totext(result)); - - isc_lex_close(lex); - isc_lex_destroy(&lex); - if (!quiet && stats) - isc_mem_stats(mctx, stdout); - isc_mem_destroy(&mctx); - - return (0); -} diff --git a/lib/dns/tests/dnstest.c b/lib/dns/tests/dnstest.c index 5167829547..cc9f9dcaab 100644 --- a/lib/dns/tests/dnstest.c +++ b/lib/dns/tests/dnstest.c @@ -10,6 +10,8 @@ #include +#include + #include #include #include @@ -19,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -353,6 +356,29 @@ fromhex(char c) { /* 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) diff --git a/lib/dns/tests/dnstest.h b/lib/dns/tests/dnstest.h index 16f620c641..6222daaa1f 100644 --- a/lib/dns/tests/dnstest.h +++ b/lib/dns/tests/dnstest.h @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id$ */ - /*! \file */ #include @@ -79,3 +77,6 @@ dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, 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); diff --git a/lib/dns/tests/rdata_test.c b/lib/dns/tests/rdata_test.c index 31c0f8f875..20c06b2dcc 100644 --- a/lib/dns/tests/rdata_test.c +++ b/lib/dns/tests/rdata_test.c @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id$ */ - /*! \file */ #include @@ -16,6 +14,7 @@ #include +#include #include #include @@ -24,11 +23,599 @@ #include "dnstest.h" -/* - * Individual unit tests - */ +/***** + ***** Commonly used structures + *****/ -/* Successful load test */ +/* + * An array of these structures is passed to check_text_ok(). + */ +struct text_ok { + const char *data; /* RDATA in text format */ + isc_boolean_t ok; /* is this RDATA valid? */ + int lineno; /* source line in which RDATA is defined */ +}; +typedef struct text_ok text_ok_t; + +/* + * An array of these structures is passed to check_wire_ok(). + */ +struct wire_ok { + unsigned char data[64]; /* RDATA in wire format */ + size_t len; /* octets of data to parse */ + isc_boolean_t ok; /* is this RDATA valid? */ + int lineno; /* source line in which RDATA is defined */ +}; +typedef struct wire_ok wire_ok_t; + +/***** + ***** Convenience macros for creating the above structures + *****/ + +#define TEXT_VALID(data) { data, ISC_TRUE, __LINE__ } +#define TEXT_INVALID(data) { data, ISC_FALSE, __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(ISC_TRUE, __VA_ARGS__) +#define WIRE_INVALID(...) WIRE_TEST(ISC_FALSE, __VA_ARGS__) +#define WIRE_SENTINEL() WIRE_TEST(ISC_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); +} + +/* + * Test whether supplied RDATA in text format is properly handled as having + * either valid or invalid syntax for an RR of given rdclass and type. + */ +static void +check_text_ok_single(const text_ok_t *text_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) { + isc_buffer_t source, target; + unsigned char buf[1024]; + isc_lex_t *lex = NULL; + isc_result_t result; + dns_rdata_t rdata; + size_t length; + + /* + * Set up lexer to read data. + */ + result = isc_lex_create(mctx, 64, &lex); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + length = strlen(text_ok->data); + isc_buffer_constinit(&source, text_ok->data, length); + isc_buffer_add(&source, length); + result = isc_lex_openbuffer(lex, &source); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + /* + * Initialize target structures. + */ + isc_buffer_init(&target, buf, sizeof(buf)); + dns_rdata_init(&rdata); + /* + * Try converting RDATA text into uncompressed wire form. + */ + result = dns_rdata_fromtext(&rdata, rdclass, type, lex, dns_rootname, + 0, NULL, &target, NULL); + /* + * Check whether result is as expected. + */ + if (text_ok->ok) + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + else + ATF_REQUIRE(result != ISC_R_SUCCESS); + /* + * If text was parsed correctly, perform additional two-way + * rdata <-> type-specific struct conversion checks. + */ + if (result == ISC_R_SUCCESS) + check_struct_conversions(&rdata, structsize, text_ok->lineno); + + isc_lex_destroy(&lex); +} + +/* + * Test whether supplied RDATA in wire format 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)), + 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)), + wire_ok->len); + /* + * If data was parsed correctly, perform additional two-way + * rdata <-> type-specific struct conversion checks. + */ + if (result == ISC_R_SUCCESS) + check_struct_conversions(&rdata, structsize, wire_ok->lineno); +} + +/* + * For each text RDATA in the supplied array, check whether it is properly + * handled as having either valid or invalid syntax for an RR of given rdclass + * and type. This checks whether the fromtext_*() routine for given RR class + * and type behaves as expected. + */ +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].data != 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, isc_boolean_t 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 RDATA in text and/or wire form 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 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, + isc_boolean_t empty_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) { + isc_result_t result; + + result = dns_test_begin(NULL, ISC_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, ISC_FALSE, dns_rdataclass_in, + dns_rdatatype_csync, sizeof(dns_rdata_csync_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, ISC_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 " @@ -47,6 +634,9 @@ ATF_TC_BODY(hip, tc) { UNUSED(tc); + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + /* * Fill the rest of input buffer with compression pointers. */ @@ -66,550 +656,280 @@ ATF_TC_BODY(hip, tc) { 0, &target); dns_decompress_invalidate(&dctx); ATF_REQUIRE_EQ(result, DNS_R_FORMERR); -} -ATF_TC(edns_client_subnet); -ATF_TC_HEAD(edns_client_subnet, tc) { - atf_tc_set_md_var(tc, "descr", - "check EDNS client subnet option parsing"); -} -ATF_TC_BODY(edns_client_subnet, tc) { - struct { - unsigned char data[64]; - size_t len; - isc_boolean_t ok; - } test_data[] = { - { - /* option code with no content */ - { 0x00, 0x08, 0x0, 0x00 }, 4, ISC_FALSE - }, - { - /* Option code family 0, source 0, scope 0 */ - { - 0x00, 0x08, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00 - }, - 8, ISC_TRUE - }, - { - /* Option code family 1 (ipv4), source 0, scope 0 */ - { - 0x00, 0x08, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x00 - }, - 8, ISC_TRUE - }, - { - /* Option code family 2 (ipv6) , source 0, scope 0 */ - { - 0x00, 0x08, 0x00, 0x04, - 0x00, 0x02, 0x00, 0x00 - }, - 8, ISC_TRUE - }, - { - /* extra octet */ - { - 0x00, 0x08, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x00, - 0x00 - }, - 9, ISC_FALSE - }, - { - /* source too long for IPv4 */ - { - 0x00, 0x08, 0x00, 8, - 0x00, 0x01, 33, 0x00, - 0x00, 0x00, 0x00, 0x00 - }, - 12, ISC_FALSE - }, - { - /* source too long for IPv6 */ - { - 0x00, 0x08, 0x00, 20, - 0x00, 0x02, 129, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }, - 24, ISC_FALSE - }, - { - /* scope too long for IPv4 */ - { - 0x00, 0x08, 0x00, 8, - 0x00, 0x01, 0x00, 33, - 0x00, 0x00, 0x00, 0x00 - }, - 12, ISC_FALSE - }, - { - /* scope too long for IPv6 */ - { - 0x00, 0x08, 0x00, 20, - 0x00, 0x02, 0x00, 129, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }, - 24, ISC_FALSE - }, - { - /* length too short for source generic */ - { - 0x00, 0x08, 0x00, 5, - 0x00, 0x00, 17, 0x00, - 0x00, 0x00, - }, - 19, ISC_FALSE - }, - { - /* length too short for source ipv4 */ - { - 0x00, 0x08, 0x00, 7, - 0x00, 0x01, 32, 0x00, - 0x00, 0x00, 0x00, 0x00 - }, - 11, ISC_FALSE - }, - { - /* length too short for source ipv6 */ - { - 0x00, 0x08, 0x00, 19, - 0x00, 0x02, 128, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }, - 23, ISC_FALSE - }, - { - /* sentinal */ - { 0x00 }, 0, ISC_FALSE - } - }; - unsigned char buf[1024*1024]; - isc_buffer_t source, target1; - dns_rdata_t rdata; - dns_decompress_t dctx; - isc_result_t result; - size_t i; - - UNUSED(tc); - - for (i = 0; test_data[i].len != 0; i++) { - isc_buffer_init(&source, test_data[i].data, test_data[i].len); - isc_buffer_add(&source, test_data[i].len); - isc_buffer_setactive(&source, test_data[i].len); - isc_buffer_init(&target1, 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_opt, &source, - &dctx, 0, &target1); - dns_decompress_invalidate(&dctx); - if (test_data[i].ok) - ATF_CHECK_EQ(result, ISC_R_SUCCESS); - else - ATF_CHECK(result != ISC_R_SUCCESS); - } -} - -ATF_TC(wks); -ATF_TC_HEAD(wks, tc) { - atf_tc_set_md_var(tc, "descr", "wks to/from struct"); -} -ATF_TC_BODY(wks, tc) { - struct { - unsigned char data[64]; - size_t len; - isc_boolean_t ok; - } test_data[] = { - { - /* too short */ - { 0x00, 0x08, 0x0, 0x00 }, 4, ISC_FALSE - }, - { - /* minimal TCP */ - { 0x00, 0x08, 0x0, 0x00, 6 }, 5, ISC_TRUE - }, - { - /* minimal UDP */ - { 0x00, 0x08, 0x0, 0x00, 17 }, 5, ISC_TRUE - }, - { - /* minimal other */ - { 0x00, 0x08, 0x0, 0x00, 1 }, 5, ISC_TRUE - }, - { - /* sentinal */ - { 0x00 }, 0, ISC_FALSE - } - }; - unsigned char buf1[1024]; - unsigned char buf2[1024]; - isc_buffer_t source, target1, target2; - dns_rdata_t rdata; - dns_decompress_t dctx; - isc_result_t result; - size_t i; - dns_rdata_in_wks_t wks; - - UNUSED(tc); - - for (i = 0; test_data[i].len != 0; i++) { - isc_buffer_init(&source, test_data[i].data, test_data[i].len); - isc_buffer_add(&source, test_data[i].len); - isc_buffer_setactive(&source, test_data[i].len); - isc_buffer_init(&target1, buf1, sizeof(buf1)); - dns_rdata_init(&rdata); - dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); - result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, - dns_rdatatype_wks, &source, - &dctx, 0, &target1); - dns_decompress_invalidate(&dctx); - if (test_data[i].ok) - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - else - ATF_REQUIRE(result != ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) - continue; - result = dns_rdata_tostruct(&rdata, &wks, NULL); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - isc_buffer_init(&target2, buf2, sizeof(buf2)); - dns_rdata_reset(&rdata); - result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in, - dns_rdatatype_wks, &wks, - &target2); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), - test_data[i].len); - ATF_REQUIRE_EQ(memcmp(buf2, test_data[i].data, - test_data[i].len), 0); - } -} - -ATF_TC(isdn); -ATF_TC_HEAD(isdn, tc) { - atf_tc_set_md_var(tc, "descr", "isdn to/from struct"); -} -ATF_TC_BODY(isdn, tc) { - struct { - unsigned char data[64]; - size_t len; - isc_boolean_t ok; - } test_data[] = { - { - /* "" */ - { 0x00 }, 1, ISC_TRUE - }, - { - /* "\001" */ - { 0x1, 0x01 }, 2, ISC_TRUE - }, - { - /* "\001" "" */ - { 0x1, 0x01, 0x00 }, 3, ISC_TRUE - }, - { - /* "\000" "\001" */ - { 0x1, 0x01, 0x01, 0x01 }, 4, ISC_TRUE - }, - { - /* sentinal */ - { 0x00 }, 0, ISC_FALSE - } - }; - unsigned char buf1[1024]; - unsigned char buf2[1024]; - isc_buffer_t source, target1, target2; - dns_rdata_t rdata; - dns_decompress_t dctx; - isc_result_t result; - size_t i; - dns_rdata_isdn_t isdn; - - UNUSED(tc); - - for (i = 0; test_data[i].len != 0; i++) { - isc_buffer_init(&source, test_data[i].data, test_data[i].len); - isc_buffer_add(&source, test_data[i].len); - isc_buffer_setactive(&source, test_data[i].len); - isc_buffer_init(&target1, buf1, sizeof(buf1)); - dns_rdata_init(&rdata); - dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); - result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, - dns_rdatatype_isdn, &source, - &dctx, 0, &target1); - dns_decompress_invalidate(&dctx); - if (test_data[i].ok) - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - else - ATF_REQUIRE(result != ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) - continue; - result = dns_rdata_tostruct(&rdata, &isdn, NULL); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - isc_buffer_init(&target2, buf2, sizeof(buf2)); - dns_rdata_reset(&rdata); - result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in, - dns_rdatatype_isdn, &isdn, - &target2); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), - test_data[i].len); - ATF_REQUIRE_EQ(memcmp(buf2, test_data[i].data, - test_data[i].len), 0); - } -} - -static void -error_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, ...) { - UNUSED(callbacks); - UNUSED(fmt); -} - -static void -warn_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, ...) { - UNUSED(callbacks); - UNUSED(fmt); -} - -ATF_TC(nsec); -ATF_TC_HEAD(nsec, tc) { - atf_tc_set_md_var(tc, "descr", "nsec to/from text/wire"); -} -ATF_TC_BODY(nsec, tc) { - struct { - const char *data; - isc_boolean_t ok; - } text_data[] = { - { "", ISC_FALSE }, - { ".", ISC_FALSE }, - { ". RRSIG", ISC_TRUE }, - { NULL, ISC_FALSE }, - }; - struct { - unsigned char data[64]; - size_t len; - isc_boolean_t ok; - } wire_data[] = { - { { 0x00 }, 0, ISC_FALSE }, - { { 0x00 }, 1, ISC_FALSE }, - { { 0x00, 0x00 }, 2, ISC_FALSE }, - { { 0x00, 0x00, 0x00 }, 3, ISC_FALSE }, - { { 0x00, 0x00, 0x01, 0x02 }, 4, ISC_TRUE } - }; - unsigned char buf1[1024], buf2[1024]; - isc_buffer_t source, target1, target2; - isc_result_t result; - size_t i; - dns_rdataclass_t rdclass = dns_rdataclass_in; - dns_rdatatype_t type = dns_rdatatype_nsec; - isc_lex_t *lex = NULL; - dns_rdatacallbacks_t callbacks; - dns_rdata_nsec_t nsec; - dns_decompress_t dctx; - - UNUSED(tc); - - result = dns_test_begin(NULL, ISC_FALSE); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - - result = isc_lex_create(mctx, 64, &lex); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - - dns_rdatacallbacks_init(&callbacks); - callbacks.error = error_callback; - callbacks.warn = warn_callback; - - for (i = 0; text_data[i].data != NULL; i++) { - size_t length = strlen(text_data[i].data); - isc_buffer_constinit(&source, text_data[i].data, length); - isc_buffer_add(&source, length); - result = isc_lex_openbuffer(lex, &source); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - - isc_buffer_init(&target1, buf1, sizeof(buf1)); - - result = dns_rdata_fromtext(NULL, rdclass, type, lex, - dns_rootname, 0, NULL, &target1, - &callbacks); - if (text_data[i].ok) - ATF_CHECK_EQ(result, ISC_R_SUCCESS); - else - ATF_CHECK(result != ISC_R_SUCCESS); - } - isc_lex_destroy(&lex); - - for (i = 0; i < sizeof(wire_data)/sizeof(wire_data[0]); i++) { - dns_rdata_t rdata = DNS_RDATA_INIT; - - isc_buffer_init(&source, wire_data[i].data, wire_data[i].len); - isc_buffer_add(&source, wire_data[i].len); - isc_buffer_setactive(&source, wire_data[i].len); - isc_buffer_init(&target1, buf1, sizeof(buf1)); - dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); - result = dns_rdata_fromwire(&rdata, rdclass, type, &source, - &dctx, 0, &target1); - dns_decompress_invalidate(&dctx); - if (wire_data[i].ok) - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - else - ATF_REQUIRE(result != ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) - continue; - result = dns_rdata_tostruct(&rdata, &nsec, NULL); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - isc_buffer_init(&target2, buf2, sizeof(buf2)); - dns_rdata_reset(&rdata); - result = dns_rdata_fromstruct(&rdata, rdclass, type, - &nsec, &target2); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), - wire_data[i].len); - ATF_REQUIRE_EQ(memcmp(buf2, wire_data[i].data, - wire_data[i].len), 0); - } -} - -ATF_TC(csync); -ATF_TC_HEAD(csync, tc) { - atf_tc_set_md_var(tc, "descr", "csync to/from struct"); -} -ATF_TC_BODY(csync, tc) { - struct { - const char *data; - isc_boolean_t ok; - } text_data[] = { - { "", ISC_FALSE }, - { "0", ISC_FALSE }, - { "0 0", ISC_TRUE }, - { "0 0 A", ISC_TRUE }, - { "0 0 NS", ISC_TRUE }, - { "0 0 AAAA", ISC_TRUE }, - { "0 0 A AAAA", ISC_TRUE }, - { "0 0 A NS AAAA", ISC_TRUE }, - { "0 0 A NS AAAA BOGUS", ISC_FALSE }, - { NULL, ISC_FALSE }, - }; - struct { - unsigned char data[64]; - size_t len; - isc_boolean_t ok; - } wire_data[] = { - /* short */ - { { 0x00 }, 0, ISC_FALSE }, - /* short */ - { { 0x00 }, 1, ISC_FALSE }, - /* short */ - { { 0x00, 0x00 }, 2, ISC_FALSE }, - /* short */ - { { 0x00, 0x00, 0x00 }, 3, ISC_FALSE }, - /* short */ - { { 0x00, 0x00, 0x00, 0x00 }, 4, ISC_FALSE }, - /* short */ - { { 0x00, 0x00, 0x00, 0x00, 0x00 }, 5, ISC_FALSE }, - /* serial + flags only */ - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 6, ISC_TRUE }, - /* bad type map */ - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 7, ISC_FALSE }, - /* bad type map */ - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - 8, ISC_FALSE }, - /* good type map */ - { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02 }, - 9, ISC_TRUE } - }; - unsigned char buf1[1024]; - unsigned char buf2[1024]; - isc_buffer_t source, target1, target2; - isc_result_t result; - size_t i; - dns_rdataclass_t rdclass = dns_rdataclass_in; - dns_rdatatype_t type = dns_rdatatype_csync; - isc_lex_t *lex = NULL; - dns_rdatacallbacks_t callbacks; - dns_rdata_csync_t csync; - dns_decompress_t dctx; - - UNUSED(tc); - - result = dns_test_begin(NULL, ISC_FALSE); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - - result = isc_lex_create(mctx, 64, &lex); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - - dns_rdatacallbacks_init(&callbacks); - callbacks.error = error_callback; - callbacks.warn = warn_callback; - - for (i = 0; text_data[i].data != NULL; i++) { - size_t length = strlen(text_data[i].data); - isc_buffer_constinit(&source, text_data[i].data, length); - isc_buffer_add(&source, length); - result = isc_lex_openbuffer(lex, &source); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - - isc_buffer_init(&target1, buf1, sizeof(buf1)); - - result = dns_rdata_fromtext(NULL, rdclass, type, lex, - dns_rootname, 0, NULL, &target1, - &callbacks); - if (text_data[i].ok) - ATF_CHECK_EQ(result, ISC_R_SUCCESS); - else - ATF_CHECK(result != ISC_R_SUCCESS); - } - isc_lex_destroy(&lex); - - for (i = 0; i < sizeof(wire_data)/sizeof(wire_data[0]); i++) { - dns_rdata_t rdata = DNS_RDATA_INIT; - - isc_buffer_init(&source, wire_data[i].data, wire_data[i].len); - isc_buffer_add(&source, wire_data[i].len); - isc_buffer_setactive(&source, wire_data[i].len); - isc_buffer_init(&target1, buf1, sizeof(buf1)); - dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); - result = dns_rdata_fromwire(&rdata, rdclass, type, &source, - &dctx, 0, &target1); - dns_decompress_invalidate(&dctx); - if (wire_data[i].ok) - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - else - ATF_REQUIRE(result != ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) - continue; - result = dns_rdata_tostruct(&rdata, &csync, NULL); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - isc_buffer_init(&target2, buf2, sizeof(buf2)); - dns_rdata_reset(&rdata); - result = dns_rdata_fromstruct(&rdata, rdclass, type, - &csync, &target2); - ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), - wire_data[i].len); - ATF_REQUIRE_EQ(memcmp(buf2, wire_data[i].data, - wire_data[i].len), 0); - } + dns_test_end(); } /* - * Main + * 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: + * + * ISDN + * + * The field is required; is optional. + * + * identifies the ISDN number of 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 syntactically + * identical to that used in TXT and HINFO. + * + * specifies the subaddress (SA). The format of in master + * files is a syntactically identical to that used in + * TXT and HINFO. + * + * The format of ISDN is class insensitive. ISDN RRs cause no + * additional section processing. + * + * The 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 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 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, ISC_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, ISC_FALSE, dns_rdataclass_in, + dns_rdatatype_nsec, sizeof(dns_rdata_nsec_t)); +} + +/* + * WKS tests. + * + * RFC 1035: + * + * 3.4.2. WKS RDATA format + * + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ADDRESS | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | PROTOCOL | | + * +--+--+--+--+--+--+--+--+ | + * | | + * / / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * where: + * + * ADDRESS An 32 bit Internet address + * + * PROTOCOL An 8 bit IP protocol number + * + * 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, ISC_FALSE, dns_rdataclass_in, + dns_rdatatype_wks, sizeof(dns_rdata_in_wks_t)); +} + +/***** + ***** Main + *****/ + ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, hip); + ATF_TP_ADD_TC(tp, csync); ATF_TP_ADD_TC(tp, edns_client_subnet); - ATF_TP_ADD_TC(tp, wks); + ATF_TP_ADD_TC(tp, hip); ATF_TP_ADD_TC(tp, isdn); ATF_TP_ADD_TC(tp, nsec); - ATF_TP_ADD_TC(tp, csync); + ATF_TP_ADD_TC(tp, wks); return (atf_no_error()); }