]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] Refactor RDATA unit tests
authorMichał Kępień <michal@isc.org>
Tue, 25 Jul 2017 05:34:27 +0000 (07:34 +0200)
committerMichał Kępień <michal@isc.org>
Tue, 1 Aug 2017 10:15:21 +0000 (12:15 +0200)
4667. [cleanup] Refactor RDATA unit tests. [RT #45610]

CHANGES
bin/tests/Makefile.in
bin/tests/rdata_test.c [deleted file]
lib/dns/tests/dnstest.c
lib/dns/tests/dnstest.h
lib/dns/tests/rdata_test.c

diff --git a/CHANGES b/CHANGES
index ee2025ff43c786fe7caf15254b211fa85f46858e..d6dee6a332d8d3d80338bf19b809ba65f7ab028a 100644 (file)
--- 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
index 533683090d7d3fc52c1ffe2ab5a552c209bf2e43..e80ad0be23c32e66f92fa5a2e982d6c6e0698e51 100644 (file)
@@ -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 (file)
index 7156114..0000000
+++ /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 <config.h>
-
-#include <stdlib.h>
-
-#include <isc/buffer.h>
-#include <isc/commandline.h>
-#include <isc/lex.h>
-#include <isc/mem.h>
-#include <isc/print.h>
-#include <isc/string.h>
-#include <isc/util.h>
-
-#include <dns/rdata.h>
-#include <dns/compress.h>
-#include <dns/rdataclass.h>
-#include <dns/rdatastruct.h>
-#include <dns/rdatatype.h>
-#include <dns/result.h>
-
-
-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, &region);
-                       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);
-}
index 516782954741be38272e20d9fed7ff58b319e9d4..cc9f9dcaab0158845ffee306902fc98be313c8ae 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <config.h>
 
+#include <atf-c.h>
+
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
@@ -19,6 +21,7 @@
 #include <isc/entropy.h>
 #include <isc/file.h>
 #include <isc/hash.h>
+#include <isc/hex.h>
 #include <isc/mem.h>
 #include <isc/os.h>
 #include <isc/print.h>
@@ -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)
index 16f620c64158f0e73f7d2865e9774be3a8a4f724..6222daaa1f80f6d2c5c6993b2c67e87914bc0c45 100644 (file)
@@ -6,8 +6,6 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-/* $Id$ */
-
 /*! \file */
 
 #include <config.h>
@@ -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);
index 31c0f8f875f763980e7b5dd6e82891aacc9ff209..20c06b2dcc95d20f781ab3fa484e33eeb2a3e099 100644 (file)
@@ -6,8 +6,6 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-/* $Id$ */
-
 /*! \file */
 
 #include <config.h>
@@ -16,6 +14,7 @@
 
 #include <unistd.h>
 
+#include <isc/hex.h>
 #include <isc/lex.h>
 #include <isc/types.h>
 
 
 #include "dnstest.h"
 
+/*****
+ ***** Commonly used structures
+ *****/
+
+/*
+ * 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);
+}
+
 /*
- * Individual unit tests
+ * 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;
 
-/* Successful load test */
+       /*
+        * 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);
-       }
+       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 to/from struct");
+       atf_tc_set_md_var(tc, "descr", "ISDN RDATA manipulations");
 }
 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
-               }
+       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()
        };
-       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);
+       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 to/from text/wire");
+       atf_tc_set_md_var(tc, "descr", "NSEC RDATA manipulations");
 }
 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 },
+       text_ok_t text_ok[] = {
+               TEXT_INVALID(""),
+               TEXT_INVALID("."),
+               TEXT_VALID(". RRSIG"),
+               TEXT_SENTINEL()
        };
-       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 }
+       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()
        };
-       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);
-       }
+       check_rdata(text_ok, wire_ok, ISC_FALSE, dns_rdataclass_in,
+                   dns_rdatatype_nsec, sizeof(dns_rdata_nsec_t));
 }
 
-ATF_TC(csync);
-ATF_TC_HEAD(csync, tc) {
-       atf_tc_set_md_var(tc, "descr", "csync to/from struct");
+/*
+ * 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(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 }
+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()
        };
-       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);
-       }
+       check_rdata(NULL, wire_ok, ISC_FALSE, dns_rdataclass_in,
+                   dns_rdatatype_wks, sizeof(dns_rdata_in_wks_t));
 }
 
-/*
- * Main
- */
+/*****
+ ***** 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());
 }